Linux進程間通信(四)---信號通信之信號發送捕捉kill()、raise()、alarm()、pause()及其基礎實驗


信號概述

   ●  信號是在軟件層次上對中斷機制的一種模擬。在原理上,一個進程收到一個信號與處理器收到一個中斷請求可以說是一樣的。

   ●  信號是異步的,一個進程不必通過任何操作來等待信號的到達,事實上進程也不知道信號到底什么時候到達。

   ●  信號可以直接進行用戶空間進程和內核進程之間的交互,內核進程也可以利用它來通知用戶空間進程發生了哪些系統事件。它可以在任何時候發給某一個進程,而無需知道該進程的狀態。如果該信號當前並未處於執行態(Running),則該信號由內核保存起來,直到該進程恢復執行再傳遞給它為止。如果一個信號被進程設置為阻塞,則該信號的傳遞被延遲,直到其阻塞被取消時才被傳遞給進程。

   ●  信號是進程間通信機制中唯一的異步通信機制,可以看作是異步通知,通知接收信號的進程有哪些事件發生了。信號機制除了基本通知外,還可以傳遞附加信息。

信號來源

     信號事件發生的來源有兩種:

     ① 硬件來源。如我們按下了鍵盤上的按鈕 或者出現其他硬件故障;

     ② 軟件來源。最常用發送信號的系統函數有kill()、raise()、alarm()、setitimer()和sigqueue()等,軟件來源還包括一些非法運算等操作。

進程響應信號的方式

    ① 忽略信號。忽略信號即對信號不做處理,其中,有兩個信號不能忽略:SIGKILL和SIGSTOP。

    ② 捕捉信號。定義信號處理函數,當信號發生時,執行響應的處理函數。

    ③ 執行默認操作。Linux對每種信號都規定了默認操作,如下表所示:

   


信號的生命周期

     一個完整的信號生命周期可以分為3個重要階段,這3個階段由4個重要事件來刻畫的;信號產生、信號在進程中注冊、信號在進程中注銷、執行信號處理函數。這里信號的產生、注冊、注銷等是指信號的內部實現機制,而不是信號的函數實現(不受我們的掌控)。因此信號注冊與否與后面講到的發送信號函數(如 kill()等)及信號安裝函數(如 signal()等)無關,只與信號值有關。

   相鄰兩個事件的時間間隔構成信號生命周期的一個階段,如下圖1.注意這里的信號處理有多種方式,一般是由內核完成的,當然也可以由用戶進程來完成。

   

    信號的處理包括信號的發送、捕捉和處理,它們有各自相對應的常見函數:

    ●  發生信號的函數: kill()、raise()。 

    ●  捕捉信號的函數: alarm()、pause()。

    ●  處理信號的函數: signal()、sigaction()。

  本節主要講信號的發送與捕捉,下一節再講處理

信號發送函數 kill()和raise()

函數說明

   kill()函數同咱們的kill系統命令一樣(但不能誤以為kill()就是kill哈),可以發送信號給進程或進程組(實際上,kill系統命令只是kill()函數的一個用戶接口)。這里需要注意的是,kill()函數不僅可以終止進程(實際上是通過發出SIGKILL信號終止),也可以向進程發送其他信號。

   與kill()函數不同的是,raise()函數允許進程向自身發送信號。

函數格式

   下表分別列出了kill()和raise()的格式

      

      


基礎實驗

   本實驗首先使用 fork()創建了一個子進程,接着為了保證子進程不在父進程調用kill()之前退出,在子進程中使用raise()函數向自身發送 SIGSTOP信號,使子進程暫停。接下來在父進程中調用kill()向子進程發送信號,在該實驗中使用的是SIGKILL。實驗代碼如下:

   kill_raise.c文件點此下載

      

   編譯后執行的效果如下圖

   

   你瞧瞧,多狠啊,都不讓子進程輸出第22行的話,直接啪的就給人拍那里了。

   另外,建議你去掉27行的代碼再執行一遍試一試看看有什么不同。

信號捕捉函數: alarm()、pause()

函數說明

    alarm()也稱為鬧鍾函數,它可以在進程中設置一個定時器,當定時器指定的時間到時,它就向進程發送SIGALARM信號。要注意的是,一個進程只能有一個鬧鍾時間,如果在調用alarm()之前已設置過鬧鍾時間,則任何以前的鬧鍾時間都被新值所代替。

   pause()函數用於將調用進程掛起直至捕捉到信號為止。這個函數很常用,通常可以用於判斷信號是否已到。

函數格式

   

    



基礎實驗

    本實驗實際上是完成了一個簡單的sleep()函數的功能,程序如下圖

     

   編譯執行后,結果如下圖

   

  可以看到12行的語句根本就沒執行,其實想想程序的執行流程就很清除,首先程序定時,執行到11行pause();時進程會被掛起,當計時到,發出信號SIGALARM,這時pause()捕捉到信號,進程直接被終止。

    現在屏蔽掉11行,如下

    

   再次編譯執行,結果如下圖

   

  下一節學習一下信號的處理,如需轉載,請注明出處:http://blog.csdn.net/mybelief321/article/details/9078193

  最后,順祝大家端午節快樂!!也順祝今年的金九銀十順利!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM