前面我們學(xué)習(xí)了信號(hào)產(chǎn)生的幾種方式,而對(duì)于信號(hào)的處理有如下幾種方式:
默認(rèn)處理方式;
忽略;
捕捉。
信號(hào)的捕捉,說白了就是抓到一個(gè)信號(hào)后,執(zhí)行我們指定的函數(shù),或者執(zhí)行我們指定的動(dòng)作。下面詳細(xì)介紹兩個(gè)信號(hào)捕捉操作參數(shù):signal和sigaction。
##signal函數(shù)
函數(shù)原型:
sighandler_t signal(int signum, sighandler_t handler);
其中,sighandler定義是這樣的:typedef void (*sighandler_t)(int);
函數(shù)作用:注冊(cè)一個(gè)信號(hào)捕捉函數(shù),也就是說,收到了某個(gè)信號(hào),就執(zhí)行它所注冊(cè)的回調(diào)函數(shù)。
函數(shù)參數(shù):
signum:信號(hào)編號(hào),盡量用宏來寫,而別用數(shù)字,這樣更適合跨平臺(tái);
handler:注冊(cè)的回調(diào)函數(shù);
函數(shù)缺陷:
由于歷史原因,該函數(shù)在不同版本的Unix和Linux系統(tǒng)中可能起到的效果不一樣,所以跨平臺(tái)性不佳,盡量避免使用它,取而代之使用通用性更好的sigaction函數(shù)。
##sigaction函數(shù)
函數(shù)原型:
int sigaction(int signum, const struct sigaction act, struct sigaction oldact);
函數(shù)作用:與signal函數(shù)類似,用來注冊(cè)一個(gè)信號(hào)捕捉函數(shù);
返回值:
成功:0;失敗:-1,并設(shè)置errno;
參數(shù):
signum:信號(hào)編號(hào),盡量用宏來寫,而別用數(shù)字,這樣更適合跨平臺(tái);
act:傳入?yún)?shù),新的信號(hào)捕捉方式;
oldact:傳出參數(shù),舊的信號(hào)捕捉方式
這里特別要注意參數(shù)中struct sigaction結(jié)構(gòu)體,這也是這個(gè)函數(shù)的難點(diǎn)所在,下面詳細(xì)說明:
struct sigaction結(jié)構(gòu)體
原型:
這個(gè)結(jié)構(gòu)體成員很多,又很多是回調(diào)函數(shù)的形式,令人望而生畏。但實(shí)際上,需要掌握的只有三個(gè)。
首先,sa_restorer和sa_sigaction這兩個(gè)成員一個(gè)已經(jīng)被棄用了,另一個(gè)很少使用,所以我們暫且不管它們,重點(diǎn)掌握剩下的三個(gè)。
(1) sa_handler:指定信號(hào)捕捉后的處理函數(shù),即注冊(cè)回調(diào)函數(shù)。該成員也可以賦值為SIG_IGN,表示忽略該信號(hào),也可注冊(cè)為SIG_DFL,表示執(zhí)行信號(hào)的默認(rèn)動(dòng)作。
(2) sa_mask:臨時(shí)阻塞信號(hào)集(或信號(hào)屏蔽字)先來看這樣一個(gè)情景:
某個(gè)信號(hào)已經(jīng)注冊(cè)了回調(diào)函數(shù),當(dāng)內(nèi)核傳遞這個(gè)信號(hào)過來時(shí),會(huì)先經(jīng)過一個(gè)阻塞信號(hào)集,先阻塞掉部分信號(hào)。再去執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)。如下圖示:
假如說,這個(gè)回調(diào)函數(shù)回調(diào)執(zhí)行的時(shí)間比較長(zhǎng),比如2秒,在這2秒里,又有其它的信號(hào)過來,那進(jìn)程是暫停當(dāng)前回調(diào)函數(shù),去響應(yīng)新的信號(hào),還是不管新來的信號(hào),先把當(dāng)前回調(diào)函數(shù)處理完再說?
正確的做法是,在執(zhí)行回調(diào)函數(shù)期間,使用sa_mask臨時(shí)的去替代進(jìn)程的阻塞信號(hào)集,保證回調(diào)函數(shù)安心的執(zhí)行完畢,再解除替代。注意:這個(gè)過程僅僅發(fā)生在回調(diào)函數(shù)執(zhí)行期間,是臨時(shí)性的設(shè)置。
(3) sa_flags:通常設(shè)置為0,表示使用默認(rèn)屬性。
再來看另外一個(gè)場(chǎng)景:
比如進(jìn)程對(duì)SIGQUIT注冊(cè)了回調(diào)函數(shù),當(dāng)回調(diào)函數(shù)在執(zhí)行期間,又來了SIGQUIT函數(shù),這時(shí),進(jìn)程是響應(yīng)還是不響應(yīng)該信號(hào)?這就是sa_flags的一個(gè)作用,當(dāng)其設(shè)置為0時(shí),表示使用默認(rèn)屬性,也就是先不響應(yīng)該信號(hào),而是執(zhí)行完回調(diào)函數(shù)再處理此信號(hào)。
另外,阻塞的常規(guī)信號(hào)不支持排隊(duì),也就是說,執(zhí)行回調(diào)函數(shù)期間,再來千百個(gè)同個(gè)信號(hào)時(shí),系統(tǒng)只記錄一次。而后面的32個(gè)實(shí)時(shí)信號(hào)則支持排隊(duì)。
責(zé)編AJX
-
Linux
+關(guān)注
關(guān)注
87文章
11345瀏覽量
210394 -
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6892瀏覽量
123744 -
信號(hào)
+關(guān)注
關(guān)注
11文章
2804瀏覽量
77104
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
原創(chuàng)丨Linux系統(tǒng)編程篇丨迅為IMX6ULL-對(duì)應(yīng)視頻講解
Linux操作系統(tǒng)安裝與使用
為何將Linux操作系統(tǒng)劃分為用戶和內(nèi)核
Linux操作系統(tǒng)安裝與使用
Linux操作系統(tǒng)安裝與使用方法
什么是Linux系統(tǒng)編程
是否可以為linux操作系統(tǒng)編譯并在基于debian的rasperry操作系統(tǒng)中運(yùn)行?
Linux操作系統(tǒng)知識(shí)講解:走進(jìn)Linux 內(nèi)存使用場(chǎng)景
![<b class='flag-5'>Linux</b><b class='flag-5'>操作系統(tǒng)</b>知識(shí)<b class='flag-5'>講解</b>:走進(jìn)<b class='flag-5'>Linux</b> 內(nèi)存使用場(chǎng)景](https://file.elecfans.com/web1/M00/C5/1A/o4YBAF9Ic1yADtJ0AACDHiuU3OU400.png)
評(píng)論