生活随笔
收集整理的這篇文章主要介紹了
详细解释signal和sigaction以及SIG_BLOCK
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
signal,此函數相對簡單一些,給定一個信號,給出信號處理函數則可,當然,函數簡單,其功能也相對簡單許多,簡單給出個函數例子如下:
?
[cpp]?view plain?copy
?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?????//?(void)?signal(SIGINT,?SIG_DFL);???9?????//(void)?signal(SIGINT,?ouch);??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 plain?copy
stuct?sigaction??{????????void?(*)(int)?sa_handle;????????sigset_t?sa_mask;????????int?sa_flags;??}??
?
[cpp]?view plain?copy
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?????//?act.sa_flags?=?SA_RESETHAND;???26?????//?act.sa_flags?=?SA_NODEFER;???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 plain?copy
#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
--------------------- 本文來自 Kevin_Smart 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/davion_zhang/article/details/52247675?utm_source=copy
總結
以上是生活随笔為你收集整理的详细解释signal和sigaction以及SIG_BLOCK的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。