http://blog.csdn.net/zzyoucan/article/details/9235685
信號:信號是unix中最古老的進程通信的一種方式,他是軟件層次上對中斷機制的模擬,是一種異步通信方式,信號可以實現用戶空間進程和內核空間進程的交互,內核進程可以利用他通知用戶空間進程發生了哪些系統事件,我們可以任何時候給進程發送信號而無需知道進程的狀態,如果進程當前并未處于執行態,則信號則會由內核保存起來,如果進程是阻塞狀態,那么信號傳遞會被延遲,直到阻塞結束時才會傳遞給進程。
看一下kill -l列出的各種命令:
會發現一個規律,前32種信號會有各種不同的名稱,后32種會以“SIGRTMIN”或者“SIGRTMAX”開頭,前者是從unix繼承下來的信號,稱為不可靠信號(也稱為非實時信號),后者為了解決“不可靠信號”的問題進行了更改和擴充的信號形成了可靠信號(也稱為實時信號)
如果想要了解可靠與不可靠信號,需要了解信號的生命周期:
一個完整的信號周期可以分為三個重要階段,三個重要階段有四個重要事件刻畫的:信號產生,信號在進程中注冊,信號在進程中注銷,執行信號處理函數
信號處理周期:
相鄰的兩個事件的時間間隔構成了生命周期的一個階段,這里的信號處理有多種方式,一般由內核完成,也可以由用戶進程完成
可靠信號與不可靠信號的區別:
不可靠信號如果發現信號已經在進程中注冊,就會忽略該信號,因此若前一個信號還沒有注銷又產生了新的信號就是導致信號丟失
可靠信號發送給一個進程時,不管該信號是否已經在進程中注冊,都會被再注冊一次,因此信號不會丟失,所有可靠信號都支持排隊,所有不可靠信號都不支持排隊。
ps:這里信號的產生,注冊,注銷等是指信號的內部的實現機制,而不是調用信號的函數實現,所以信號注冊與否,與本節后面講到的發送信號函數(kill等)以及信號安裝函數(signal()等)無關只與信號值有關
用戶進程對信號的響應有三種方式:
- 忽略信號,對信號不做任何處理,但是又兩個信號是不能忽略的,即SIGKILL,SIGSTOP
- 捕捉信號,定義信號處理函數,當信號發送時,執行相應的自定義處理函數
- 執行缺省操作,linux對每種信號都規定了默認操作
linux中大多數信號是提供給內核的,下面列出了最為常見的信號的含義及其默認操作:
發送信號的函數主要有kill(),raise(),alarm(),pause()
(1)kill()和raise()
kill()函數和熟知的kill系統命令一樣,可以發送信號給信號和進程組(實際上kill系統命令只是kill函數的一個用戶接口),需要注意的是他不僅可以終止進程(發送SIGKILL信號),也可以向進程發送其他信號。
與kill函數不同的是raise()函數允許進程向自身發送信號。
(2)函數格式:
kill函數的語法格式:
raise()函數語法要點:
下面的例子使子進程不在父進程調用kill之前不退出,然后父進程調用kill使子進程退出:
程序運行結果如下:
看出父進程kill掉了子進程
(3)alarm()和pause()
alarm()-----也稱為鬧鐘函數,可以在進程中設置一個定時器,等到時間到達時,就會想進程發送SIGALARM信號,注意的是一個進程只能有一個鬧鐘時間,如果調用alarm()之前已經設置了鬧鐘時間,那么任何以前的鬧鐘時間都會被新值所代替
pause()----此函數用于將進程掛起直到捕捉到信號為止,這個函數很常用,通常用于判斷信號是否已到
alarm()函數語法:
pause()函數語法如下:
下面的一個實例實現了sleep()函數的功能
執行程序會在5秒之后出現:
這個函數中的printf是不會執行的,因為定時器發送的SIGARAM的默認處理是終止程序,所以程序打印之前程序已經結束了,與sleep不同的是sleep是不會退出的。