Linux信号实践(4) --可靠信号
Sigaction
#include <signal.h> int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);功能:
? ?sigaction函數用于改變進程接收到特定信號后的行為。
參數
? ?第一個參數為信號的值,可以為除SIGKILL及SIGSTOP外的任何一個特定有效的信號(為這兩個信號定義自己的處理函數,將導致信號安裝錯誤)
? ?第二個參數是指向結構sigaction的指針,在結構?sigaction的實例中,指定了對特定信號的處理,可以為空,進程會以缺省方式對信號處理
? ?第三個參數oldact指向的對象用來保存原來對相應信號的處理,可指定oldact為NULL。
返回值:函數成功返回0,失敗返回-1
?
sigaction結構體
? 第二個參數最為重要,其中包含了對指定信號的處理、信號所傳遞的信息、信號處理函數執(zhí)行過程中應屏蔽掉哪些函數等等
struct sigaction { //信號處理程序 不接受額外數據(比較過時)void (*sa_handler)(int);//信號處理程序能接受額外數據,和sigqueue配合使用(支持信號排隊,信號傳送其他信息),推薦使用void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; //屏蔽int sa_flags; //表示信號的行為:SA_SIGINFO表示能接受數據void (*sa_restorer)(void); //廢棄不用了 }; //簡單示例1: 用sigaction簡單替換signal函數 void signalAction(int signo, siginfo_t *signalInfo, void *p) {cout << "signal = " << signo << ", desc: " << strsignal(signo) << endl; }int main() {struct sigaction act;//注意:回調函數句柄sa_handler、sa_sigaction只能選其一!!!//act.sa_handler = sigHandler;act.sa_sigaction = signalAction;sigemptyset(&act.sa_mask);act.sa_flags = 0;if (sigaction(SIGINT,&act,NULL) == -1)err_exit("sigaction error");pause(); } //簡單實例2: 用sigaction模擬signal函數 sighandler_t mySignal(int signum, sighandler_t handler) {struct sigaction act;struct sigaction oldAct;act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;if (sigaction(signum, &act, &oldAct) == -1)return SIG_ERR;return oldAct.sa_handler; }sa_mask選項
? ? sa_mask?specifies?a?mask?of?signals?which?should?be?blocked/**?指定一個信號集的掩碼,?在這個掩碼中的信號將要阻塞**/ ? ? ?(i.e.,?added??to??the??signal?mask?of?the?thread?in?which?the?signal?handler?is?invoked)?
during?execution?of?the?signal?handler.??In?addition,?the?signal?which?triggered?the?handler?will?be?blocked,?
unless?the?SA_NODEFER?flag?is?used.
? /**?在執(zhí)行handler?的時候,?如果此時進程收到了sa_mask所包含的信號,?則這些信號將不會被響應,?直到handler函數執(zhí)行完畢
與sigprocmask不同是:?sigprocmask?是指定該進程的信號屏蔽字->?屏蔽該信號,?不會接收該信號,?而sa_mask則是接收了該信號,?但是不會相應該信號**/
//示例: 將sa_mask選項設置以后的效果 /** 在進程相應SIGINT信號時, 如果此時有SIGQUIT信號抵達, SIGQUIT信號也不會被響應, 直到SIGINT信號相應完成之后, 才會去相應SIGQUIT信號(如運行截圖所示)**/ int main() {struct sigaction act;act.sa_handler = sigHandler;sigemptyset(&act.sa_mask);// 添加下面一行后: 在響應SIGINT信號時, 是不會被中斷的sigaddset(&act.sa_mask, SIGQUIT);act.sa_flags = 0;if (sigaction(SIGINT, &act, NULL) == -1)err_exit("sigaction error");while (true)pause(); } void sigHandler(int signo) {cout << "catch a signal, signo = " << signo << ", desc: " << strsignal(signo) << endl;sleep(10); }//運行截圖
?
?
sa_flags:?詳細信息
?
siginfo_t結構:
siginfo_t{int si_signo; /* Signal number */int si_errno; /* An errno value */int si_code; /* Signal code */int si_trapno; /* Trap number that causedhardware-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 */long si_band; /* Band event (was int inglibc 2.3.2 and earlier) */int si_fd; /* File descriptor */short si_addr_lsb; /* Least significant bit of address(since Linux 2.6.32) */ }sigqueue
#include <signal.h> int sigqueue(pid_t pid, int sig, const union sigval value);功能
? ?sigqueue是新的發(fā)送信號系統調用,主要是針對實時信號提出的支持信號帶有參數,與函數sigaction()配合使用。
? ?和kill函數相比多了一個參數:const?union?sigval?value(int?kill(pid_t?pid,?int?sig)),因此sigqueue()可以比kill()傳遞更多的信息,但sigqueue()只能向一個進程發(fā)送信號,而不能發(fā)送信號給一個進程組。
參數
? ?參數1是指定接收信號的進程id,參數2確定即將發(fā)送的信號;
? ?參數3是一個聯合數據結構union?sigval,指定了信號傳遞的參數,即通常所說的4字節(jié)值。
sigval聯合體
typedef union sigval{int sival_int;void *sival_ptr; } sigval_t; //綜合實驗sigaction+sigqueue void onSa_SignalAction(int signalNum, siginfo_t *signalInfo, void *p) {cout << "signalNum = " << signalNum << endl;//int recValue = signalInfo -> si_value.sival_int; 同下int recValue = signalInfo -> si_int;cout << "recvValue = " << recValue << endl; }int main() {struct sigaction act;sigemptyset(&act.sa_mask);act.sa_flags = SA_SIGINFO;act.sa_sigaction = onSa_SignalAction;if (sigaction(SIGINT,&act,NULL) == -1)err_exit("sigaction error");pid_t pid = fork();if (pid == -1)err_exit("fork error");else if (pid == 0) //In Child{/*typedef union sigval{int sival_int;void *sival_ptr;} sigval_t;*///union sigval signalValue; 同下sigval_t signalValue;signalValue.sival_int = 256;sleep(2);//給父進程發(fā)送SIGINT信號sigqueue(getppid(),SIGINT,signalValue);}pause();return 0; }總結
以上是生活随笔為你收集整理的Linux信号实践(4) --可靠信号的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 技术人员为什么应该参加社区活动?
- 下一篇: oracle的imp和exp