sigaction函數 sigaction函數的功能是用於改變進程接收到特定信號后的行為。 int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact); 參數 --第一個參數是信號的值,可以為除了SIGKILL及SIGSTOP外的任何一個特定有效的信號(因為這兩個信號定義了自己的處理函數,將導致信號安裝錯誤) --第二個參數是指向節后sigaction的一個實例的指針,在sigaction的實例中,指定了對特定信號的處理,可以為NULL,進程會以缺省方式對信號處理 --第三個參數oldact指向的對象用來保存原來對相應信號的處理,可以為NULL 返回值:函數成功返回0,失敗返回-1。
sigaction函數檢查或修改與指定信號相關聯的處理動作,該函數取代了signal函數。
因為signal函數在信號未決時接收信號可能出現問題,所以使用sigaction更安全。
sigaction結構體 struct sigaction { void (*sa_handler)(int);//信號處理程序 不接受額外數據 void (*sa_sigaction)(int, siginfo_t *, void *);//信號處理程序,能接受額外數據,可以和sigqueue配合使用 sigset_t sa_mask; int sa_flags;//影響信號的行為SA_SIGINFO表示能接受數據 void (*sa_restorer)(void);//廢棄 }; --第二個參數最為重要,其中包含了對指定信號的處理、信號所傳遞的信息、信號處理函數執行過程中贏屏蔽掉哪些函數等等。 --回調函數sa_handler、sa_sigaction只能任選其一
//捕捉信號 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <signal.h> void catch_signal(int sign) { switch(sign) { case SIGINT: //SIGINT默認行為是退出進程 printf("SIGINT signal\n"); exit(0); break; case SIGALRM: //SIGALRM默認行為是退出進程 printf("SIGALRM signal\n"); break; case SIGKILL: printf("SIGKILL signal\n"); break; } } //建議使用封裝之后的mysignal int mysignal(int sign,void (*func)(int)) { struct sigaction act,oact; //傳入回調函數 act.sa_handler=func; //將act的屬性sa_mask設置一個初始值 sigemptyset(&act.sa_mask); act.sa_flags=0; return sigaction(sign,&act,&oact); } int main(int arg, char *args[]) { mysignal(SIGINT,catch_signal); mysignal(SIGALRM,catch_signal); mysignal(SIGKILL,catch_signal); int i=0; while(1) { printf("hello god %d\n",i++); sleep(1); } return 0; }
sigqueue函數 --新的發送信號系統調用,主要是針對實時信號提出的支持信號帶有參數,與sigaction()函數配合使用 --注意:和kill函數相比int kill(pid_t pid,int signo)多了參數 --原型 int sigqueue(pid_t pid,int signo,const union sigval value); --參數 sigqueue的第一個參數是指定接收信號的進程pid,第二個參數確定即將發送的信號,
第三個參數是一個聯合數據結構union sigval,指定了信號傳遞的參數,即通常所說的4字節值。 --函數成功返回0,失敗返回-1,並且更新errno --sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向一個進程發送信號,而不能發送信號給一個進程組 --union sigval聯合體 typedef union sigval { int sival_int; void * sival_ptr; }sigval_t;
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> /* siginfo_t { int si_signo; // Signal number int si_errno; // An errno value int si_code; // Signal code int si_trapno; // Trap number that caused hardware-generated signal (unused on most architectures) pid_t si_pid; // Sending process ID uid_t si_uid; // Real user ID of sending process int si_status; // Exit value or signal clock_t si_utime; // User time consumed clock_t si_stime; // System time consumed sigval_t si_value; // Signal value int si_int; // POSIX.1b signal void *si_ptr; // POSIX.1b signal int si_overrun; // Timer overrun count; POSIX.1b timers int si_timerid; // Timer ID; POSIX.1b timers void *si_addr; // Memory location which caused fault int si_band; // Band event int si_fd; // File descriptor } */ void catch_signal(int signo,siginfo_t *resdata,void *unkonwp) { printf("signo=%d\n",signo); printf("return data :%d\n",resdata->si_value.sival_int); printf("second return data:%d\n",resdata->si_int); return ; } int main(int arg, char *args[]) { pid_t pid=0; pid=fork(); if(pid==-1) { printf("fork() failed! error message:%s\n",strerror(errno)); return -1; } if(pid==0) { printf("i am child!\n"); //等待父進程執行完信號安裝 sleep(5); //向父進程發送帶數據的信號 union sigval sigvalue; sigvalue.sival_int=222; //發送信號 if(sigqueue(getppid(),SIGINT,sigvalue)==-1) { printf("sigqueue() failed ! error message:%s\n",strerror(errno)); exit(0); } printf("子進程信號發送成功!\n"); exit(0); } if(pid>0) { printf("i am father!\n"); //安裝信號 struct sigaction act; //初始化sa_mask sigemptyset(&act.sa_mask); act.sa_sigaction=catch_signal; //一旦使用了sa_sigaction屬性,那么必須設置sa_flags屬性的值為SA_SIGINFO act.sa_flags=SA_SIGINFO; //安裝信號 if(sigaction(SIGINT,&act,NULL)!=0) { printf("sigaction() failed! \n"); return -1; } //等待子進程返回 int status=0; wait(&status); printf("game over!\n"); } return 0; }