二 Pthread 并發編程( 四 )


除此之外我們還可以設置線程自己的信號掩碼,在前文當中我們已經提到了 , 每個線程都擁有線程自己的掩碼,因此在下面的程序當中只有線程 2 響應了主線程發送的 SIGTERM 信號 。
#define _GNU_SOURCE#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <signal.h>#include <string.h>void sig(int signo) {  char s[1024];  sprintf(s, "signo = %d tid = %d pthread tid = %ld\n", signo, gettid(), pthread_self());  write(STDOUT_FILENO, s, strlen(s));}void* func(void* arg) {  sigset_t set;  sigemptyset(&set);  sigaddset(&set, SIGTERM);  pthread_sigmask(SIG_BLOCK, &set, NULL);  // 上面的代碼的功能是阻塞 SIGTERM 這個信號 當這個信號傳輸過來的時候不會立即執行信號處理函數  // 而是會等到將這個信號變成非阻塞的時候才會響應  printf("func : pthread tid = %ld\n", pthread_self());  for(;;);  return NULL;}void* func02(void* arg) {  printf("func02 : pthread tid = %ld\n", pthread_self());  for(;;);  return NULL;}int main() {  signal(SIGTERM, sig);  pthread_t t1;  pthread_create(&t1, NULL, func, NULL);  sleep(1);  pthread_t t2;  pthread_create(&t2, NULL, func02, NULL);  sleep(1);  pthread_kill(t1, SIGTERM);  pthread_kill(t2, SIGTERM);  sleep(2);  return 0;}在上面的程序當中我們創建了兩個線程并且定義了 SIGTERM 的信號處理函數,在線程 1 執行的函數當中修改了自己阻塞的信號集,將 SIGTERM 變成了一種阻塞信號,也就是說當線程接受到 SIGTERM 的信號的時候不會立即調用 SIGTERM 的信號處理函數,只有將這個信號變成非阻塞的時候才能夠響應這個信號 , 執行對應的信號處理函數 , 但是線程 t2 并沒有阻塞信號 SIGTERM ,因此線程 t2 會執行對應的信號處理函數,上面的程序的輸出結果如下所示:
func : pthread tid = 139887896323840func02 : pthread tid = 139887887931136signo = 15 tid = 10652 pthread tid = 139887887931136根據上面程序的輸出結果我們可以知道線程 t2 確實調用了信號處理函數(根據 pthread tid )可以判斷,而線程 t1 沒有執行信號處理函數 。
在上文當中我們還提到了在一個進程當中,所有的線程共享同一套信號處理函數,如果在一個線程里面重新定義了一個信號的處理函數,那么他將會影響其他的線程,比如下面的程序:
#define _GNU_SOURCE#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <signal.h>#include <string.h>void sig(int signo) {  char s[1024];  sprintf(s, "signo = %d tid = %d pthread tid = %ld\n", signo, gettid(), pthread_self());  write(STDOUT_FILENO, s, strlen(s));}void sig2(int signo) {  char* s = "thread-defined\n";  write(STDOUT_FILENO, s, strlen(s));}void* func(void* arg) {  signal(SIGSEGV, sig2);  printf("pthread tid = %ld\n", pthread_self());  for(;;);  return NULL;}void* func02(void* arg) {  printf("pthread tid = %ld\n", pthread_self());  for(;;);  return NULL;}int main() {  signal(SIGSEGV, sig);  pthread_t t;  pthread_create(&t, NULL, func, NULL);  sleep(1);  pthread_t t2;  pthread_create(&t2, NULL, func02, NULL);  sleep(1);  pthread_kill(t2, SIGSEGV);  sleep(2);  return 0;}上面的程序的輸出結果如下所示:
pthread tid = 140581246330624pthread tid = 140581237937920thread-defined從上面程序輸出的結果我們可以看到線程 t2 執行的信號處理函數是 sig2 而這個信號處理函數是在線程 t1 執行的函數 func 當中進行修改的,可以看到線程 t1 修改的結果確實得到了響應 , 從這一點也可以看出,如果一個線程修改信號處理函數是會影響到其他的線程的 。

推薦閱讀