1. 程式人生 > >Linux多執行緒中使用訊號 (轉)

Linux多執行緒中使用訊號 (轉)

       但是在多執行緒中處理訊號的原則卻完全不同,它的基本原則是:將對訊號的非同步處理,轉換成同步處理,也就是說用一個執行緒專門的來“同步等待”訊號的到來,而其它的執行緒可以完全不被該訊號中斷/打斷(interrupt)。這樣就在相當程度上簡化了在多執行緒環境中對訊號的處理。而且可以保證其它的執行緒不受訊號的影響。這樣我們對訊號就可以完全預測,因為它不再是非同步的,而是同步的我們完全知道訊號會在哪個執行緒中的哪個執行點到來而被處理!。而同步的程式設計模式總是比非同步的程式設計模式簡單。其實多執行緒相比於多程序的其中一個優點就是:多執行緒可以將程序中非同步的東西轉換成同步的來處理。

1. sigwait函式:
sigwait等一個或者多個指定訊號發生。
    它所做的工作只有兩個:第一,監聽被阻塞的訊號;第二,如果所監聽的訊號產生了,則將其從未決佇列中移出來(這裡實時訊號和非實時訊號又有區別,體現在取出的順序等,具體自己取網上查,這裡不再詳述)。sigwait並不改變訊號掩碼的阻塞與非阻塞狀態。在POSIX標準中,當程序收到訊號時,如果是多執行緒的情況,我們是無法確定是哪一個執行緒處理這個訊號。而sigwait是從程序中pending的訊號中,取走指定的訊號。這樣的話,如果要確保sigwait這個執行緒收到該訊號,那麼所有執行緒含主執行緒以及這個sigwait執行緒則必須block住這個訊號,因為如果自己不阻塞就沒有未決狀態(阻塞狀態)訊號,別的所有執行緒不阻塞就有可能當訊號過來時,被其他的執行緒處理掉。
記住:     在多執行緒程式碼中,總是使用sigwait或者sigwaitinfo或者sigtimedwait等函式來處理訊號。     而不是signal或者sigaction等函式。因為在一個執行緒中呼叫signal或者sigaction等函式會改變所以執行緒中的     訊號處理函式。而不是僅僅改變呼叫signal/sigaction的那個執行緒的訊號處理函式。

2. pthread_sigmask函式:每個執行緒均有自己的訊號遮蔽集(訊號掩碼),可以使用pthread_sigmask函式來遮蔽某個執行緒對某些訊號的   響應處理,僅留下需要處理該訊號的執行緒來處理指定的訊號。實現方式是:利用執行緒訊號遮蔽集的繼承關係
  (在主程序中對sigmask進行設定後,主程序創建出來的執行緒將繼承主程序的掩碼

3. pthread_kill函式:   在多執行緒程式中,一個執行緒可以使用pthread_kill對同一個程序中指定的執行緒(包括自己)傳送訊號。注意在多執行緒中    一般不使用kill函式傳送訊號,因為kill是對程序傳送訊號,結果是:正在執行的執行緒會處理該訊號,如果該執行緒沒有 註冊訊號處理函式,那麼會導致整個程序退出。記住:呼叫sigwait同步等待的訊號必須在呼叫執行緒中被遮蔽,並且通常應該在所有的執行緒中被遮蔽(這樣可以保證訊號絕不會被送到除了呼叫sigwait的任何其它執行緒),這是通過利用訊號掩碼的繼承關係來達到的。