本示例中,SigThread专用线程等待SIGUSR1信号。线程接收到该信号后,在互斥量的保护下修改全局标志gWorkFlag,然后调用pthread_cond_signal()唤醒WkrThread线程。WkrThread线程使用相同的互斥量检查全局标志的值,并原子地释放互斥量,等待条件发生。当条件满足时,该线程进入工作状态。
  编译链接后,执行结果如下:

 

1 [wangxiaoyuan_@localhost~ ]$ ./Sigwait &
2 [1] 3940
3 [wangxiaoyuan_@localhost~ ]$ Worker thread starts!
4 kill -USR1 3940
5 Worker thread starts working...
6 [wangxiaoyuan_@localhost~ ]$ ps
7   PID TTY          TIME CMD
8  3940 pts/12   00:00:31 Sigwait
9  4836 pts/12   00:00:00 ps
10 32206 pts/12   00:00:00 bash
11 [wangxiaoyuan_@localhost~ ]$ kill -KILL 3940
12 [wangxiaoyuan_@localhost~ ]$ ps
13   PID TTY          TIME CMD
14  5664 pts/12   00:00:00 ps
15 32206 pts/12   00:00:00 bash
16 [1]+  Killed                  ./Sigwait

  其中,命令kill -USR1和kill -KILL分别等同于kill -10和kill -9。
  这种唤醒方式也可用于线程退出,而且比轮询方式高效。
  3.4 示例4
  本示例将sigwait()可用于主线程,即可正常捕捉信号,又不必考虑异步信号安全性。
  1 int main(void)
  2 {
  3     //1. 创建工作线程(pthread_create)
  4     //2. 等待终端键入的SIGINT信号(sigwait)
  5     //3. 执行清理操作
  6     //4. 程序退出(exit)
  7 }
  该例中主要等待SIGINT/SIGQUIT等终端信号,然后退出程序。
  四  总结
  Linux线程编程中,需谨记两点:1)信号处理由进程中所有线程共享;2)一个信号只能被一个线程处理。具体编程实践中,需注意以下事项:
  不要在线程信号屏蔽字中阻塞、等待和捕获不可忽略的信号(不起作用),如SIGKILL和SIGSTOP。
  不要在线程中阻塞或等待SIGFPE/SIGILL/SIGSEGV/SIGBUS等硬件致命错误,而应捕获它们。
  在创建线程前阻塞这些信号(新线程继承信号屏蔽字),然后仅在sigwait()中隐式地解除信号集的阻塞。
  不要在多个线程中调用sigwait()等待同一信号,应设置一个调用该函数的专用线程。
  闹钟定时器是进程资源,且进程内所有线程共享相同的SIGALARM信号处理,故它们不可能互不干扰地使用闹钟定时器。
  当一个线程试图唤醒另一线程时,应使用条件变量,而不是信号。