生活随笔
收集整理的這篇文章主要介紹了
linux 信号signal和sigaction理解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉載:http://blog.csdn.net/beginning1126/article/details/8680757
今天看到unp時發現之前對signal到理解實在淺顯,今天拿來單獨學習討論下。
signal,此函數相對簡單一些,給定一個信號,給出信號處理函數則可,當然,函數簡單,其功能也相對簡單許多,簡單給出個函數例子如下:
[cpp]?view plaincopy
?1?#include?<signal.h>?? ?2?#include?<stdio.h>?? ?3?#include?<unistd.h>?? ?4??? ?5?void?ouch(int?sig)?? ?6?{?? ?7?????printf("I?got?signal?%d\n",?sig);?? ?8??????? ?9??????? 10??? 11?}?? 12??? 13??? 14??? 15?int?main()?? 16?{?? 17?????(void)?signal(SIGINT,?ouch);?? 18??? 19?????while(1)?? 20?????{?? 21?????????printf("hello?world...\n");?? 22?????????sleep(1);?? 23?????}?? 24?}??
當然,實際運用中,需要對不同到signal設定不同的到信號處理函數,SIG_IGN忽略/SIG_DFL默認,這倆宏也可以作為信號處理函數。同時SIGSTOP/SIGKILL這倆信號無法捕獲和忽略。注意,經過實驗發現,signal函數也會堵塞當前正在處理的signal,但是沒有辦法阻塞其它signal,比如正在處理SIG_INT,再來一個SIG_INT則會堵塞,但是來SIG_QUIT則會被其中斷,如果SIG_QUIT有處理,則需要等待SIG_QUIT處理完了,SIG_INT才會接著剛才處理。
sigaction,這個相對麻煩一些,函數原型如下:
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
函數到關鍵就在于struct sigaction
[cpp]?view plaincopy
stuct?sigaction?? {?? ??????void?(*)(int)?sa_handle;?? ??????sigset_t?sa_mask;?? ??????int?sa_flags;?? }??
[cpp]?view plaincopy
1?#include?<signal.h>?? ??2?#include?<stdio.h>?? ??3?#include?<unistd.h>?? ??4??? ??5??? ??6?void?ouch(int?sig)?? ??7?{?? ??8?????printf("oh,?got?a?signal?%d\n",?sig);?? ??9??? ?10?????int?i?=?0;?? ?11?????for?(i?=?0;?i?<?5;?i++)?? ?12?????{?? ?13?????????printf("signal?func?%d\n",?i);?? ?14?????????sleep(1);?? ?15?????}?? ?16?}?? ?17??? ?18??? ?19?int?main()?? ?20?{?? ?21?????struct?sigaction?act;?? ?22?????act.sa_handler?=?ouch;?? ?23?????sigemptyset(&act.sa_mask);?? ?24?????sigaddset(&act.sa_mask,?SIGQUIT);?? ?25??????? ?26??????? ?27?????act.sa_flags?=?0;?? ?28??? ?29?????sigaction(SIGINT,?&act,?0);?? ?30??? ?31??? ?32?????struct?sigaction?act_2;?? ?33?????act_2.sa_handler?=?ouch;?? ?34?????sigemptyset(&act_2.sa_mask);?? ?35?????act.sa_flags?=?0;?? ?36?????sigaction(SIGQUIT,?&act_2,?0);?? ?37??? ????????while(1)?? ????????{?? ?????????????sleep(1);?? ????????}?? ?38?????return;?? ?? ????}??
1. 阻塞,sigaction函數有阻塞的功能,比如SIGINT信號來了,進入信號處理函數,默認情況下,在信號處理函數未完成之前,如果又來了一個SIGINT信號,其將被阻塞,只有信號處理函數處理完畢,才會對后來的SIGINT再進行處理,同時后續無論來多少個SIGINT,僅處理一個SIGINT,sigaction會對后續SIGINT進行排隊合并處理。
2. sa_mask,信號屏蔽集,可以通過函數sigemptyset/sigaddset等來清空和增加需要屏蔽的信號,上面代碼中,對信號SIGINT處理時,如果來信號SIGQUIT,其將被屏蔽,但是如果在處理SIGQUIT,來了SIGINT,則首先處理SIGINT,然后接著處理SIGQUIT。
3.?sa_flags如果取值為0,則表示默認行為。還可以取如下倆值,但是我沒覺得這倆值有啥用。
SA_NODEFER,如果設置來該標志,則不進行當前處理信號到阻塞
SA_RESETHAND,如果設置來該標志,則處理完當前信號后,將信號處理函數設置為SIG_DFL行為
下面單獨來討論一下信號屏蔽,記住是屏蔽,不是消除,就是來了信號,如果當前是block,則先不傳遞給當前進程,但是一旦unblock,則信號會重新到達。
[cpp]?view plaincopy
#include?<signal.h>?? #include?<stdio.h>?? #include?<unistd.h>?? ?? ?? ?? static?void?sig_quit(int);?? ?? int?main?(void)?{?? ????sigset_t?new,?old,?pend;?? ?????? ????signal(SIGQUIT,?sig_quit);?? ?? ????sigemptyset(&new);?? ????sigaddset(&new,?SIGQUIT);?? ????sigprocmask(SIG_BLOCK,?&new,?&old);?? ?? ????sleep(5);?? ?? ????printf("SIGQUIT?unblocked\n");?? ????sigprocmask(SIG_SETMASK,?&old,?NULL);?? ?? ????sleep(50);?? ????return?1;?? }?? ?? static?void?sig_quit(int?signo)?{?? ????printf("catch?SIGQUIT\n");?? ????signal(SIGQUIT,?SIG_DFL);?? }??
gcc -g -o mask mask.c?
./mask
========這個地方按多次ctrl+\
SIGQUIT unblocked
catch SIGQUIT
Quit (core dumped)
======================
注意觀察運行結果,在sleep的時候,按多次ctrl+\,由于sleep之前block了SIG_QUIT,所以無法獲得SIG_QUIT,但是一旦運行sigprocmask(SIG_SETMASK, &old, NULL);則unblock了SIG_QUIT,則之前發送的SIG_QUIT隨之而來。
由于信號處理函數中設置了DFL,所以再發送SIG_QUIT,則直接coredump。
總結
以上是生活随笔為你收集整理的linux 信号signal和sigaction理解的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。