二 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 修改的结果确实得到了响应 , 从这一点也可以看出,如果一个线程修改信号处理函数是会影响到其他的线程的 。

推荐阅读