1. 程式人生 > >訊號被掛起,sigwait()函式的作用

訊號被掛起,sigwait()函式的作用

在Linux的多執行緒中使用訊號機制,與在程序中使用訊號機制有著根本的區別,可以說是完全不同。在程序環境中,對訊號的處理是,先註冊訊號處理函式,當訊號非同步發生時,呼叫處理函式來處理訊號。它完全是非同步的(我們完全不知到訊號會在程序的那個執行點到來!)。然而訊號處理函式的實現,有著許多的限制;比如有一些函式不能在訊號處理函式中呼叫;再比如一些函式read、recv等呼叫時會被非同步的訊號給中斷(interrupt),因此我們必須對在這些函式在呼叫時因為訊號而中斷的情況進行處理(判斷函式返回時 enno 是否等於 EINTR)。

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

  4. Description
  5. The sigwait() function suspends execution of the calling thread until the delivery of one 
  6. of the signals specified in the signal set set. The function accepts the signal (removes 
  7. it from the pending list of signals), and returns the signal number in sig
    .
  8. The operation of sigwait() is the same as sigwaitinfo(2), except that:
  9. * sigwait() only returns the signal number, rather than a siginfo_t structure describing 
  10.   the signal.
  11. * The return values of the two functions are different.
  12. Return Value
  13. On success, sigwait() returns 0. On error, it returns a positive error number.
從上面的man sigwait的描述中,我們知道:sigwait是同步的等待訊號的到來,而不是像程序中那樣是非同步的等待訊號的到來。sigwait函式使用一個訊號集作為他的引數,並且在集合中的任一個訊號發生時返回該訊號值,解除阻塞,然後可以針對該訊號進行一些相應的處理。 2. 記住:      在多執行緒程式碼中,總是使用sigwait或者sigwaitinfo或者sigtimedwait等函式來處理訊號。      而不是signal或者sigaction等函式。因為在一個執行緒中呼叫signal或者sigaction等函式會改變所以執行緒中的      訊號處理函式。而不是僅僅改變呼叫signal/sigaction的那個執行緒的訊號處理函式。 3. pthread_sigmask函式:    每個執行緒均有自己的訊號遮蔽集(訊號掩碼),可以使用pthread_sigmask函式來遮蔽某個執行緒對某些訊號的    響應處理,僅留下需要處理該訊號的執行緒來處理指定的訊號。實現方式是:利用執行緒訊號遮蔽集的繼承關係   (在主程序中對sigmask進行設定後,主程序創建出來的執行緒將繼承主程序的掩碼
  1. pthread_sigmask - examine and change mask of blocked signals
  2. #include <signal.h>
  3. int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
  4. Compile and link with -pthread.
  5. DESCRIPTION
  6. The pthread_sigmask() function is just like sigprocmask(2), with the difference that its use
  7. in multithreaded programs is explicitly specified by POSIX.1-2001.
  8. Other differences are noted in this page.
  9. For a description of the arguments and operation of this function, see sigprocmask(2).
  10. RETURN VALUE
  11. On success, pthread_sigmask() returns 0; on error, it returns an error number.
  12. NOTES
  13. A new thread inherits a copy of its creator's signal mask.
  14. (from man sigprocmask: )
  15. The behavior of the call is dependent on the value of how, as follows.
  16. SIG_BLOCK
  17. The set of blocked signals is the union of the current set and the set argument.
  18. SIG_UNBLOCK
  19. The signals in set are removed from the current set of blocked signals. It is permissible 
  20. to attempt to unblock a signal which is not blocked.
  21. SIG_SETMASK
  22. The set of blocked signals is set to the argument set.
  23. If oldset is non-NULL, the previous value of the signal mask is stored in oldset.
  24. If set is NULL, then the signal mask is unchanged (i.e., how is ignored), but the current 
  25. value of the signal mask is nevertheless returned in oldset (if it is not NULL).
4. pthread_kill函式:    在多執行緒程式中,一個執行緒可以使用pthread_kill對同一個程序中指定的執行緒(包括自己)傳送訊號。注意在多執行緒中     一般不使用kill函式傳送訊號,因為kill是對程序傳送訊號,結果是:正在執行的執行緒會處理該訊號,如果該執行緒沒有  註冊訊號處理函式,那麼會導致整個程序退出。
  1. #include <signal.h>
  2. int pthread_kill(pthread_t thread, int sig);
  3. Compile and link with -pthread.
  4. DESCRIPTION
  5. The pthread_kill() function sends the signal sig to thread, another thread in the same 
  6. process as the caller. The signal is asynchronously directed to thread.
  7. If sig is 0, then no signal is sent, but error checking is still performed; this can be 
  8. used to check for the existence of a thread ID.
  9. RETURN VALUE
  10. On success, pthread_kill() returns 0; on error, it returns an error number, and no signal 
  11. is sent.
  12. ERRORS
  13. ESRCH No thread with the ID thread could be found.
  14. EINVAL An invalid signal was specified.
5. 記住:呼叫sigwait同步等待的訊號必須在呼叫執行緒中被遮蔽,並且通常應該在所有的執行緒中被遮蔽(這樣可以保證訊號絕不會被送到除了呼叫sigwait的任何其它執行緒),這是通過利用訊號掩碼的繼承關係來達到的。 (The semantics of sigwait require that all threads (including the thread calling sigwait) have the signal masked, for   reliable operation. Otherwise, a signal that arrives not blocked in sigwait might be  delivered to another thread.) 6. 程式碼示例:(from man pthread_sigmask)
  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <signal.h>
  6. #include <errno.h>
  7. /* Simple error handling functions */
  8. #define handle_error_en(en, msg) \
  9.         do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
  10. static void *
    1. sig_thread(void *arg)
  11. {
  12.       sigset_t *set = (sigset_t *) arg;
  13.       int s, sig;
  14.       for (;;) {
  15.             s = sigwait(set, &sig);
  16.             if (!= 0)
  17.                   handle_error_en(s, "sigwait");
  18.             printf("Signal handling thread got signal %d\n", sig);
  19.       }
  20. }
  21. int
    1. main(int argc, char *argv[])
  22. {
  23.       pthread_t thread;
  24.       sigset_t set;
  25.       int s;
  26.       /* 
  27.          Block SIGINT; other threads created by main() will inherit
  28.          a copy of the signal mask. 
  29.        */
  30.       sigemptyset(&set);
  31.       sigaddset(&set, SIGQUIT);
  32.       sigaddset(&set, SIGUSR1);
  33.       s = pthread_sigmask(SIG_BLOCK, &set, NULL);
  34.       if (!= 0)
  35.             handle_error_en(s, "pthread_sigmask");
  36.       s = pthread_create(&thread, NULL, &sig_thread, (void *) &set);
  37.       if (!= 0)
  38.             handle_error_en(s, "pthread_create");
  39.       /* 
  40.         Main thread carries on to create other threads and/or do
  41.         other work 
  42.        */
  43.       pause(); /* Dummy pause so we can test program */
  44.       return 0;
  45. }
編譯執行情況:
  1. [email protected]:~/pthread/learnthread$ gcc -Wall -pthread -o pthread_sigmask pthread_sigmask.
  2. [email protected]:~/pthread/learnthread$ ./pthread_sigmask &
  3. [1] 4170
  4. [email protected]:~/pthread/learnthread$ kill -QUIT %1
  5. [email protected]:~/pthread/learnthread$ Signal handling thread got signal 3
  6. [email protected]:~/pthread/learnthread$ kill -USR1 %1
  7. [email protected]:~/pthread/learnthread$ Signal handling thread got signal 10
  8. [email protected]:~/pthread/learnthread$ kill -TERM %1
  9. [email protected]:~/pthread/learnthread$ 
  10. [1]+ Terminated ./pthread_sigmask
  11. [email protected]:~/pthread/learnthread$
這個例子演示了:通過在主執行緒中阻塞一些訊號,其它的執行緒會繼承訊號掩碼,然後專門用一個執行緒使用sigwait函式來同步的處理訊號,使其它的執行緒不受到訊號的影響。

相關推薦

訊號sigwait函式作用

在Linux的多執行緒中使用訊號機制,與在程序中使用訊號機制有著根本的區別,可以說是完全不同。在程序環境中,對訊號的處理是,先註冊訊號處理函式,當訊號非同步發生時,呼叫處理函式來處理訊號。它完全是非同步的(我們完全不知到訊號會在程序的那個執行點到來!)。然而訊號處理函式的實現,有著許多的限制;比如有一些函式

python中的分支和迴圈:for 迴圈while迴圈三元操作符斷言assert關鍵字rang函式總結

1.python中的條件語句 例:score=int(input('請輸入一個分數'))        if 100>=score>=90:              

關於心跳ajax請求pending狀態stalled時間過長的問題。涉及tcp連接異常。

.net section 解決 5.1 網絡問題 chrome瀏覽器 time iou 數據包 環境:景安快雲服務器(聽說很垃圾,但是公司買的,我也剛來),CentOS-6.8-x86_64,Apache,MySQL5.1,P

網站zy老是查詢原因---2018.11.0220%

1.網站能開啟,卻ping不通? 答:網站伺服器為了防止DoS攻擊,通常在防火牆裡設定攔截ICMP報文,而ping報文正是ICMP報文的一種,當然ping不通了。 2.在IOS記憶體池中掛掉了

關於請求頁面載入緩慢問題的追查stalled 時間過長

關於請求被掛起頁面載入緩慢問題的追查 緣起 有一個Dashboard的頁面大約有十幾個圖表,每一個圖表是一個ajax請求。 突然有一天改了頁面中間幾個圖表的查詢邏輯,導致ajax請求響應時間比較長。 然後就出現了圖表加載出現了順序等待,後面本來很快就能加載出來的圖表也

linux 下C語言程式設計2——程序的建立程序間通訊

在 linux 下利用C語言實現程序的建立,掛起和解掛操作 #include <stdio.h> #include <sys/stat.h> #include <sy

Android : 執行緒的結束和恢復

實踐證明,上述情況下,建立的執行緒並不會自動銷燬,而是仍然在後臺默默無聞地執行,直到自行結束。Android的這種設計是無可厚非的。從理論上來解釋,應用的最小執行單位是執行緒,最小資源單位是程序,一個程序可以包含多個執行緒,而多個執行緒共享同一個所屬程序的資源。因此,個人理解Android的應用其實就是一個程

Spring技術內幕——事務的建立迴歸提交事務攔截器和抽象事務管理器

在涉及單個數據庫區域性事務的事務處理中,事務的最終實現和資料庫的支援是緊密相關的。對區域性資料庫事務來說,一個事務處理的操作單元往往對應著一系列的資料庫操作。 Spring事務處理主要分以下三個主要的過程: (1)讀取和處理在Spring IoC容器中配置的事務處理屬性,並

ios9定位服務的app進入後臺三分鐘收不到經緯度應用問題及解決方式

sso 進入 ont use -c 大於 null 方案 cti 原來定位服務是10分鐘收不到定位信息就掛起定位,如今變為最短3分鐘,預計都是為了省電吧。僅僅要你開啟應用的後臺定位,而且10分鐘有一次定位,那麽蘋果就不會關閉你的線程。如今變成3分鐘。若你

模式對話方塊和非模式對話方塊、accept函式、exec函式Accepted訊號區別

一.非模式對話方塊   非模式對話方塊是和同一個程式中其它視窗操作無關的對話方塊。在字處理軟體中查詢和替換對話方塊通常是非模式的來允許同時與應用程式主視窗和對話方塊進行互動。呼叫show()來顯示非模式對話方塊。show()立即返回,這樣呼叫程式碼中的控制流將會繼續。   非模式

火狐瀏覽器惡意篡改劫持開啟同時跳出主頁和2345網頁

煩 居然被劫持了,我有一丟丟小強迫症,無法忍受同時跳出兩個頁面,還是特別醜的頁面。。。歐歐歐 醜吧 這才是寶貝 方法如下 直接上乾貨: 開啟快捷方式的圖示屬性,你會發現 在目標一欄的後邊除了路徑還會多出來一個網址,且無法修改,要求管理員許可權 百度了很多,終於解決 先把目標一欄後

Windows 多執行緒之 執行緒Suspend和重新啟用Resume

首先來一下原型展示: DWORD SuspendThread(HANDLE hThread);   DWORD ResumeThread(HANDLE hThread);   只要傳入想要掛起的執行緒控制代碼就可以了。 原理:在CreateThread的時候,執行緒核對象(

線程的啟動的兩種方法Runnable接口run的調用

ride 之前 線程終止 源碼解析 star 有意 tro thread類 override 實現並啟動線程有兩種方法1、寫一個類繼承自Thread類,重寫run方法。用start方法啟動線程2、寫一個類實現Runnable接口,實現run方法。用new Thread(Ru

jquery 的htmlval用法

span light style 用法 tmpl 容器 () log 內容 var tmpl=$("#tmpl").html(); //獲取頁面的文本內容 var cnName=$("#cnName").val(); //獲取頁面的表單文本框中的值 $("#cnN

關於scanf 與 cin gets()getline......輸入輸出字符串的區別

區別 scan 輸出字符串 回車 需要 輸入流 相同 count getline 很對人對於字符串的輸入輸出一直是比較模糊的,今天總結一下幾個常用的輸入流符號對於輸入字符串時的區別: 1.scanf(),首先 它遇到空格或回車鍵(\n)就會結束,並且會將回車符算入字符串中

jquery遍歷節點 childrennextprevsiblingsclosest()

向上 tail ram 遍歷 tar tab AD ldr jquer 方法方法描述 children() 獲取匹配元素的 子元素個數(只考慮 兒子 元素) next() 獲取 後面緊鄰的 同輩元素 prev() 獲取 前面 緊鄰的 同輩元素 sibl

jQuery中bindoneonlive這幾個繫結事件函式的區別

1、bind()方法 為每個匹配元素的特定事件繫結事件處理函式。bind()方法的底層邏輯是on()方法。 .bind() 方法是用於往文件上附加行為的主要方式。所有JavaScript事件物件,比如focus, mouseover, 和 resize,都是可以作為type引數傳遞進來

pandas stack函式可用於轉置但功能絕不僅僅限於轉置。真正的轉置是df.T

實際上轉置是df.T http://pandas.pydata.org/pandas-docs/stable/reshaping.html#reshaping-and-pivot-tables  Reshaping and Pivot Tables R

endswithrangeappend()flush() 等常見方法

Python List append()方法   描述 append() 方法用於在列表末尾新增新的物件。 語法 append()方法語法: list.append(obj) 引數 obj -- 新增到列表末尾的物件。 返回值 該方法無

ucosII移植學習過程OS_CPU_SR_Save()和OS_CPU_SR_Restore函式的解析

今天突然興起回顧了一下ucosII,本人在這方面也是小白,但研究了一下,也算有點收穫,在此記錄一下。 我們都知道,程式碼的臨界段,也叫臨界區,指的是處理時不可以分割的程式碼。一旦這部分程式碼開始執行,則不容許任何中斷打斷。為了確保臨界段程式碼的可靠執行,在進入臨界段之前一定要關閉中斷,而臨界段執