sigset 與 signal的區別?

閱讀《深刻理解UNIX系統內核》的時候,瞭解到了關於信號的使用。回想起以前本身用過 signal()來處理信號,可是當時實踐的時候有個錯誤的理解:信號處理只捕獲一次信號,後面的信號都沒捕獲到,由於沒有調用個人信號處理函數。如今看來,理解錯誤,不是由於沒捕獲到,而是捕獲到了,可是使用的是默認的信號處理函數處理了。程序員

SVR2的unix版本中的信號機制是不可靠的,存在不少缺陷,最重要的問題是信號的可靠傳送。信號處理函數不是持久有效的,並且在執行時不會屏蔽相應信號(即在執行信號處理函數的時候,有可能收到新的信號,不屏蔽的作法是:不會阻塞新信號,會直接傳遞給本進程,屏蔽的作法是:若是新信號是設爲阻塞的話,那麼內核就會記住它,但不會馬上傳遞給進程,當進程取消對新信號的阻塞後,信號將會由內核傳遞給進程,並在進程中獲得處理,這容許程序員保護代碼的臨界區,防止來自一些信號的破壞)。在這個信號機制下,有一個signal()函數。書中有這麼一段話:函數

「假設用戶爲一個特殊的信號設置了一個信號處理函數,當該信號發生時,內核會在調用該處理函數以前將信號的處理動做設置爲默認動做。若是用戶但願捕捉信號的再次發送,則每次都必須從新設置這個處理函數。」優化

也就是說,使用signal()的正確方法是這樣:unix

void sigint_handler(sig)進程

int sig;程序

{方法

       signal(SIGINT,sigint_handler);兼容

        ……handler

}阻塞

main()

{

        signal(SIGINT,sigint_handler);

}

而 sigset 系統調用制定一個持久的信號處理函數,在信號發生時,不會被重置爲默認處理動做。舊的 signal 調用被保留下來以便向後兼容,由 signal 指定的處理函數不是持久性的。

可是我在本身的機器上面嘗試用 signal 捕獲 SIGINT 信號,即使不在 sigint_handler()中再次設置信號的處理函數,下次信號到達的時候,也會調用個人信號處理函數,而不須要在信號處理函數中再次設置信號處理函數。也許是如今的版本是 SVR4或者BSD, signal 優化成了持久性吧。不過記下此文,提醒本身,之後儘可能使用sigset,少用 signal。

相關文章
相關標籤/搜索