二 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;}

经验总结扩展阅读