Linux多線程中使用訊號__Linux

來源:互聯網
上載者:User

在Linux的多線程中使用訊號機制,與在進程中使用訊號機制有著根本的區別,可以說是完全不同。在進程環境中,對訊號的處理是,先註冊訊號處理函數,當訊號非同步發生時,調用處理函數來處理訊號。它完全是非同步的(我們完全不知到訊號會在進程的那個執行點到來。)。然而訊號處理函數的實現,有著許多的限制;比如有一些函數不能在訊號處理函數中調用;再比如一些函數read、recv等調用時會被非同步訊號給中斷(interrupt),因此我們必須對在這些函數在調用時因為訊號而中斷的情況進行處理(判斷函數返回時 enno 是否等於 EINTR)。
但是在多線程中處理訊號的原則卻完全不同,它的基本原則是:將對訊號的非同步處理,轉換成同步處理,也就是說用一個線程專門的來“同步等待”訊號的到來,而其它的線程可以完全不被該訊號中斷/打斷(interrupt)。這樣就在相當程度上簡化了在多線程環境中對訊號的處理。而且可以保證其它的線程不受訊號的影響。這樣我們對訊號就可以完全預測,因為它不再是非同步,而是同步的(我們完全知道訊號會在哪個線程中的哪個執行點到來而被處理。)。而同步的編程模式總是比非同步編程模式簡單。其實多線程相比於多進程的其中一個優點就是:多線程可以將進程中非同步東西轉換成同步的來處理。
1. sigwait函數:

sigwait - wait for a signal#include <signal.h>int sigwait(const sigset_t *set, int *sig);DescriptionThe sigwait() function suspends execution of the calling thread until the delivery of one of the signals specified in the signal set set. The function accepts the signal (removes it from the pending list of signals), and returns the signal number in sig.The operation of sigwait() is the same as sigwaitinfo(2), except that:* sigwait() only returns the signal number, rather than a siginfo_t structure describing   the signal.* The return values of the two functions are different.Return ValueOn 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進行設定後,主進程建立出來的線程將繼承主進程的掩碼)
pthread_sigmask - examine and change mask of blocked signals#include <signal.h>int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);Compile and link with -pthread.DESCRIPTIONThe pthread_sigmask() function is just like sigprocmask(2), with the difference that its usein multithreaded programs is explicitly specified by POSIX.1-2001.Other differences are noted in this page.For a description of the arguments and operation of this function, see sigprocmask(2).RETURN VALUEOn success, pthread_sigmask() returns 0; on error, it returns an error number.NOTESA new thread inherits a copy of its creator's signal mask.(from man sigprocmask: )The behavior of the call is dependent on the value of how, as follows.SIG_BLOCKThe set of blocked signals is the union of the current set and the set argument.SIG_UNBLOCKThe signals in set are removed from the current set of blocked signals. It is permissible to attempt to unblock a signal which is not blocked.SIG_SETMASKThe set of blocked signals is set to the argument set.If oldset is non-NULL, the previous value of the signal mask is stored in oldset.If set is NULL, then the signal mask is unchanged (i.e., how is ignored), but the current value of the signal mask is nevertheless returned in oldset (if it is not NULL).

4. pthread_kill函數:    在多線程程式中,一個線程可以使用pthread_kill對同一個進程中指定的線程(包括自己)發送訊號。注意在多線程中     一般不使用kill函數發送訊號,因為kill是對進程發送訊號,結果是:正在啟動並執行線程會處理該訊號,如果該線程沒有  註冊訊號處理函數,那麼會導致整個進程退出。
#include <signal.h>int pthread_kill(pthread_t thread, int sig);Compile and link with -pthread.DESCRIPTIONThe pthread_kill() function sends the signal sig to thread, another thread in the same process as the caller. The signal is asynchronously directed to thread.If sig is 0, then no signal is sent, but error checking is still performed; this can be used to check for the existence of a thread ID.RETURN VALUEOn success, pthread_kill() returns 0; on error, it returns an error number, and no signal is sent.ERRORSESRCH No thread with the ID thread could be found.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)
#include <pthread.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <errno.h>/* Simple error handling functions */#define handle_error_en(en, msg) \        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)static void * sig_thread(void *arg){      sigset_t *set = (sigset_t *) arg;      int s, sig;      for (;;) {            s = sigwait(set, &sig);            if (s != 0)                  handle_error_en(s, "sigwait");            printf("Signal handling thread got signal %d\n", sig);      }}int main(int argc, char *argv[]){      pthread_t thread;      sigset_t set;      int s;      /*          Block SIGINT; other threads created by main() will inherit         a copy of the signal mask.        */      sigemptyset(&set);      sigaddset(&set, SIGQUIT);      sigaddset(&set, SIGUSR1);      s = pthread_sigmask(SIG_BLOCK, &set, NULL);      if (s != 0)            handle_error_en(s, "pthread_sigmask");      s = pthread_create(&thread, NULL, &sig_thread, (void *) &set);      if (s != 0)            handle_error_en(s, "pthread_create");      /*         Main thread carries on to create other threads and/or do        other work        */      pause(); /* Dummy pause so we can test program */      return 0;}


編譯運行情況: digdeep@ubuntu:~/pthread/learnthread$ gcc -Wall -pthread -o pthread_sigmask pthread_sigmask.c 
digdeep@ubuntu:~/pthread/learnthread$ ./pthread_sigmask &
[1] 4170
digdeep@ubuntu:~/pthread/learnthread$ kill -QUIT %1
digdeep@ubuntu:~/pthread/learnthread$ Signal handling thread got signal 3

digdeep@ubuntu:~/pthread/learnthread$ kill -USR1 %1
digdeep@ubuntu:~/pthread/learnthread$ Signal handling thread got signal 10

digdeep@ubuntu:~/pthread/learnthread$ kill -TERM %1
digdeep@ubuntu:~/pthread/learnthread$ 
[1]+ Terminated ./pthread_sigmask
digdeep@ubuntu:~/pthread/learnthread$ 這個例子示範了:通過在主線程中阻塞一些訊號,其它的線程會繼承訊號掩碼,然後專門用一個線程使用sigwait函數來同步的處理訊號,使其它的線程不受到訊號的影響。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.