歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> linux下的struct sigaction

linux下的struct sigaction

日期:2017/3/3 11:49:00   编辑:Linux技術

工作中使用案例:

struct sigaction act;
act.sa_sigaction = handleSignal;
act.sa_flags = SA_SIGINFO;
sigemptyset(&act.sa_mask);
sigaction(SIGTERM,&act,NULL);

轉linux下的struct sigaction

Linux中信號相關的一個結構體struct sigaction主要在sigaction信號安裝和sigqueue信號發送時會用到
該結構位於/usr/include/bits/sigaction.h
在裡面可以找到該結構的描述
/* Structure describing the action to be taken when a signal arrives. */
struct sigaction
{
/* Signal handler. */
#ifdef __USE_POSIX199309
union
{
/* Used if SA_SIGINFO is not set. */
__sighandler_t sa_handler;
/* Used if SA_SIGINFO is set. */
void (*sa_sigaction) (int, siginfo_t *, void *);
}
__sigaction_handler;
# define sa_handler __sigaction_handler.sa_handler
# define sa_sigaction __sigaction_handler.sa_sigaction
#else
__sighandler_t sa_handler;
#endif
/* Additional set of signals to be blocked. */
__sigset_t sa_mask;
/* Special flags. */
int sa_flags;
/* Restore handler. */
void (*sa_restorer) (void);
};
在網上查了一些書料這個結構大概是這樣的
其中,sa_restorer,已過時,POSIX不支持它,不應再被使用。
1、聯合數據結構中的兩個元素_sa_handler以及*_sa_sigaction指定信號關聯函數,即用戶指定的信號處理函數。除了可以是用戶自定義的處理函數外,還可以為SIG_DFL(采用缺省的處理方式),也可以為SIG_IGN(忽略信號)。
2、由_sa_handler指定的處理函數只有一個參數,即信號值,所以信號不能傳遞除信號值之外的任何信息;由_sa_sigaction是指定的信號處理函數帶有三個參數,是為實時信號而設的(當然同樣支持非實時信號),它指定一個3參數信號處理函數。第一個參數為信號值,第三個參數沒有使用(posix沒有規范使用該參數的標准),第二個參數是指向siginfo_t結構的指針,結構中包含信號攜帶的數據值,參數所指向的結構如下:
在/usr/include/bits/siginfo.h中是這樣定義的
是不是太復雜了,在網上有一個簡潔版我搬過來用一下
siginfo_t {
int si_signo; /*信號值,對所有信號有意義*/
int si_errno; /* errno值,對所有信號有意義*/
int si_code; /*信號產生的原因,對所有信號有意義*/
union{ /*聯合數據結構,不同成員適應不同信號*/
//確保分配足夠大的存儲空間
int _pad[SI_PAD_SIZE];
//對SIGKILL有意義的結構
struct{
...
}...
... ...
... ...
//對SIGILL, SIGFPE, SIGSEGV, SIGBUS有意義的結構
struct{
...
}...
... ...
}
}
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
3、sa_mask指定在信號處理程序執行過程中,哪些信號應當被阻塞。缺省情況下當前信號本身被阻塞,防止信號的嵌套發送,除非指定SA_NODEFER或者SA_NOMASK標志位。
注:請注意sa_mask指定的信號阻塞的前提條件,是在由sigaction()安裝信號的處理函數執行過程中由sa_mask指定的信號才被阻塞。
4、sa_flags中包含了許多標志位,包括剛剛提到的SA_NODEFER及SA_NOMASK標志位。另一個比較重要的標志位是SA_SIGINFO,當設定了該標志位時,表示信號附帶的參數可以被傳遞到信號處理函數中,因此,應該為sigaction結構中的sa_sigaction指定處理函數,而不應該為sa_handler指定信號處理函數,否則,設置該標志變得毫無意義。即使為sa_sigaction指定了信號處理函數,如果不設置SA_SIGINFO,信號處理函數同樣不能得到信號傳遞過來的數據,在信號處理函數中對這些信息的訪問都將導致段錯誤(Segmentation fault)。
注:很多文獻在闡述該標志位時都認為,如果設置了該標志位,就必須定義三參數信號處理函數。實際不是這樣的,驗證方法很簡單:自己實現一個單一參數信號處理函數,並在程序中設置該標志位,可以察看程序的運行結果。實際上,可以把該標志位看成信號是否傳遞參數的開關,如果設置該位,則傳遞參數;否則,不傳遞參數。
結構說的也差不多了,其實在我看到這些東西的時候給弄暈了好幾回,簡單的說幾句就是
如果要在某信號產生時觸發某些動作我們就可以安裝信號
signal用於安裝不可靠信號 linux現在是用sigaction實現的
sigaction用於安裝可靠信號當然他也可以安裝不可靠信號並且可以附帶更多的信息
signal安裝信號時只需傳入2個參數一個是信號的值 一個是信號發生時觸發的函數,該函數接受一個整數
sigaction安裝時有3個參數第一個參數是信號的值,第二個是sigaction結構這個結構說明了信號發生時調用的函數和其它的一些信息,主要的成員是sa_handler指定的觸發函數只帶一個參數即信號的值這和signal調用沒什麼區別,sa_sigaction指定的觸發函數帶有3個參數第一個參數是信號的值,第二個參數是包函附加信息的結構siginfo,第三個參數為空如果要傳遞附加信息給觸發函數那麼必須將傳給sigaction的第二個參數sigaction結構的sa_flag設為SA_SIGINFO
上面說了那麼多結構體和復雜的很的siginfo,其實siginfo我們在實際應用中並不需要去初始化他或者做什麼,只是在信號觸發時我們可以從這個結構體中提取一些信息。
sigaction函數原型:int sigaction(int signo,const struct sigaction *restrict act,struct sigaction *restrict oact);
//第一個參數為信號編號,第二個是sigaction結構體,第三個一般為NULL。
示例:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
static void sig_usr(int signum)
{
if(signum == SIGUSR1)
{
printf("SIGUSR1 received\n");
}
else if(signum == SIGUSR2)
{
printf("SIGUSR2 received\n");
}
else
{
printf("signal %d received\n", signum);
}
}
int main(void)
{
char buf[512];
int n;
struct sigaction sa_usr;
sa_usr.sa_flags = 0;
sa_usr.sa_handler = sig_usr; //信號處理函數
sigaction(SIGUSR1, &sa_usr, NULL);
sigaction(SIGUSR2, &sa_usr, NULL);
printf("My PID is %d\n", getpid());
while(1)
{
if((n = read(STDIN_FILENO, buf, 511)) == -1)
{
if(errno == EINTR)
{
printf("read is interrupted by signal\n");
}
}
else
{
buf
= '\0';
printf("%d bytes read: %s\n", n, buf);
}
}
return 0;
}
Copyright © Linux教程網 All Rights Reserved