信號

信號的產生、阻塞以及捕捉

用kill -l命令可以查看系統定義的信號列表:

spacer.gifwKioL1ebTirhzKZ6AAEYpHnSCJY134.png-wh_50

一、產生信號

1、如何產生信號?

(1)通過終端按鍵產生信號

    SIGINT的默認處理動作是終止進程,SIGQUIT的默認處理動作是終止進程並且 Core Dump,那麼到底什麼是Core Dump?

    當一個進程要異常終止時,可以選擇把進程的用戶空間內存數據全部保存到磁盤上,文件名通常是core,這叫做Core Dump。進程異常終止通常是因爲有 Bug,比如非法內存訪問導致段錯誤,事後可以用調試器檢查core文件以查清錯誤原因,這叫做 Post-mortem Debug。一個進程允許產生多大的core文件取決於進程的Resource Limit(這 個信息保存在PCB中)。默認是不允許產生core文件的,因爲core文件中可能包含用戶密碼等敏感信息,不安全。在開發調試階段可以用ulimit命令改變這個限制,允許產生core文 件。

    首先用ulimit命令改變Shell進程的Resource Limit,允許core文件最大爲1024K:

wKioL1ebTp6CZzxYAADAv6iRZlw540.png-wh_50

    測試代碼:

:wKioL1ebTrby25PHAADY9HuK0zE515.png-wh_50

(2)調用系統函數向進程發信號

    如:

    1、kill函數:給指定的進程發送指定的信號

wKiom1ebT3rTkFHnAABBahNgb9M571.png-wh_50

    2、raise函數:可給當前進程發送指定的信號(自己給自己發送信號)

wKioL1ebT-mR7sN8AAArzLDltyg913.png-wh_50

    3、abort函數:使當前進程接受到SIGABRT信號而異常終止

wKiom1ebT_jQ34nXAABATWT1rTs713.png-wh_50

    4、signal函數:設置某一信號的對應動作

wKioL1ebUDizZi6rAAAbUxachsA820.png-wh_50

    測試代碼:

wKioL1ebUF2A1gPhAABCcRIHgpA353.png-wh_50wKiom1ebUF3TgZE6AAAQ8heDCcI530.png-wh_50

(3)由軟件條件產生信號

    如:alarm函數:在seconds秒後給當前進程發送SIGALRM信號,默認終止當前進程。

wKiom1ebURORiohwAABbzywuhwg450.png-wh_50

wKioL1ebURTChVYaAACk3HOf6OE223.png-wh_50

wKiom1ebURSy5oEdAAAJOkSl5bc169.png-wh_50

(4)kill命令行命令,如下:

wKioL1ebUbTx8sYQAAANuyxdpEM692.png-wh_50

2、如何處理信號

     (1)忽略此信號

     (2)執行該信號的默認處理動作

     (3)提供一個信號處理函數,要求內核在處理該信號是切換時切換到用戶態執行這個處理函數,也稱捕捉一個信號。


二、阻塞信號

    實際執行信號的處理動作稱爲信號遞達(Delivery),信號從產生到遞達之間的狀態,稱爲信號未決(Pending)。進程可以選擇阻塞 (Block )某個信號。被阻塞的信號產生時將保持在未決狀態,直到進程解除對此信號的阻塞, 才執行遞達的動作。注意,阻塞和忽略是不同的,只要信號被阻塞就不會遞達,而忽略是在遞達之後可選的一種處理動作。

    信號在內核中的表示示意圖:

wKiom1ebUeiCi9sDAABi2Oj6Btw744.png-wh_50

    每個信號都有兩個標誌位分別表示阻塞(block)和未決(pending),還有一個函數指針表示處理動作。

    1、SIGHUP信號未阻塞也未產生過,當它遞達時執行默認處理動作。

    2、SIGINT信號產生過,但正在被阻塞,所以暫時不能遞達。雖然它的處理動作是忽略,但在沒 有解除阻塞之前不能忽略這個信號,因爲進程仍有機會改變處理動作之後再解除阻塞。

    3、SIGQUIT信號未產生過,一旦產生SIGQUIT信號將被阻塞,它的處理動作是用戶自定義函數sighandler。

     每個信號只有一個bit的未決標誌和阻塞標誌,非0即1,不記錄該信號產生的次數。因此,未決和阻塞標誌可以用相同的數據類型sigset_t儲存,sigset_t稱爲信號集。這個類型表示信號的有效和無效狀態。在阻塞信號集(信號屏蔽字)中即block表,1表示信號阻塞,0表示不阻塞。在未決信號集即pending表,1表示信號產生未決狀態,0表示沒有產生信號。阻塞信號集也稱爲當前進程的信號屏蔽字(Singal Mask)。這裏的屏蔽應該理解爲阻塞而不是忽略。


注:不可使用位操作操作信號集,有專有的函數操作

    信號集操作函數:

wKioL1ebUozRcchWAAAzFUQs8Qg439.png-wh_50

    sigemptyset函數:初始化set所指向的信號集,將其中所有的信號對應的bit位清零,表示該信號集不包含任何有效信號。

    sigfillset函數:初始化set所指向的信號集,使其中所有的信號對應的bit置位,表示該信號集的有效信號包括系統支持的所有信號。

    sigaddset函數:在該信號集中添加某一信號。

    sigdelset函數:在該信號集中刪除某一個信號。

    sigismember函數:判斷某一個信號是否在該信號集中。

    注意:在使用sigset_t類型的變量之前,一定要調用sigemptyset和sigfillset做初始化處理,使信號集處於確定的狀態。初始化之後就可以在該信號集中增加,刪除某種有效信號等操作。


    sigprocmask函數:讀取或更改進程中的信號屏蔽字(即阻塞信號集)

wKioL1ebUxDAHByiAABBzvE463s289.png-wh_50

    如果set是非空指針,則讀取進程的當前信號屏蔽字通過oldset參數傳出。

wKiom1ebUy_Ck59XAAFu2XGn4fA550.png-wh_50

    sigpending函數:讀取當前信號集的未決信號集

wKioL1ebU5yiz47xAAAOW5fm45Q714.png-wh_50

    測試代碼:

wKiom1ebU7HzChSKAABCeViWVH8284.png-wh_50

wKioL1ebU7Lj9KymAADWFfO6hyA287.png-wh_50

    運行效果:

wKiom1ebU7Kgp1KzAABfQg3MnMA384.png-wh_50


三、捕捉信號

     一次信號捕捉的過程需要進行4次權限的切換。

wKiom1ebVDTQdI-mAAICzOgEHa4908.png-wh_50

    當一個進程接受到信號時,並不是立即進行處理,而是在合適的時候處理,所謂合適是指從內核態返回用戶態時切換處理信號。當內核處理完異常或中斷時,會先檢查當前進程中是否有可以被遞達的信號,若有,且信號的處理動作是自定義的信號處理函數,則從內核調到用戶態執行代碼,之後進入內核態,從內核態返回用戶態即上次被中斷或異常的地方,若信號的處理方式是默認,則終止進程,若忽略,則從penging表中刪除該信號,即將1變爲0,直接跳到用戶態。


    sigaction函數:讀取和修改與指定信號相關聯的處理動作。

wKioL1ebVF_hSRX-AABEC4idXfo863.png-wh_50

    參數:

    signo:信號的編號

    act:非空時,根據act修改該信號的處理動作

    oact:非空時,傳出該信號原來的處理動作

    act和oact結構體如下:

wKioL1ebVI_z0Ub5AAAo_f5-9Uk180.png-wh_50

    將sa_handler賦值爲常數SIG_IGN傳給sigaction表示忽略信號,賦值爲常數SIG_DFL 表示執行系統默認動作,賦值爲一個函數指針表示用自定義函數捕捉信號,或者說向內核註冊 了一個信號處理函數,該函數返回值爲void,可以帶一個int參數,通過參數可以得知當前信 號的編號,這樣就可以用同一個函數處理多種信號。顯然,這也是個回調函數,不是被main 函數調用,而是被系統所調用。

sa_mask:需要額外屏蔽的信號,當信號處理函數返回時自動恢復原來的信號屏蔽字。

sa_flags:包含一些選項


    pause函數:使調用的進程掛起直到有信號遞達。

wKioL1ebVOuyxJK9AAAnimfkCGs254.png-wh_50

    1、信號的處理動作是終止,則進程終止,不執行pause(即來不及執行該函數)。

    2、信號的處理動作是忽略,則進程繼續處於掛起,pause不返回。

    3、信號的處理動作是捕捉,則調用信號處理函數後返回-1.


    測試代碼:

wKiom1ebVRjDXLunAAA_Oh0Ek-Q265.png-wh_50

wKiom1ebVRigTnhmAAAYQKatoIo036.png-wh_50

    運行效果:

wKioL1ebVRjTvMbiAAAWRRZbc4Y265.png-wh_50

    

測試普通信號中哪些可以被捕捉到,哪些不能被捕捉到。

    測試代碼:

wKioL1ebVbXh5xvDAABMGAJ4U30950.png-wh_50

wKiom1ebVbXAuPTpAAA8yWZfQQA181.png-wh_50

wKiom1ebVbXB4n0VAABJjGbs_LU801.png-wh_50

    結論:除了9和19號信號,其他的普通信號都可以被捕捉到。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章