《APUE》:同步信号处理


《Unix环境高级编程》这本书附带了许多短小精美的小程序,我在阅读此书的时候,将书上的代码按照自己的理解重写了一遍(大部分是抄书上的),加深一下自己的理解(纯看书太困了,呵呵)。此例子在Ubuntu 10.04上测试通过。

相关链接

  • 《UNIX环境高级编程》(第二版)apue.h的错误
  • Unix环境高级编程 源代码地址

程序简介:在多线程程序中等侍信号设置标志,从而让主程序退出。唯一可运行的控制线程应该是主线程和信号处理程序,所以阻塞信号足以避免错失标志的修改。另外在线程中,需要使用互斥量来保护标志。以下这个程序演示了这方面的内容。

  1. //《APUE》程序12-6:同步信号处理   
  2. #include <stdio.h>   
  3. #include <stdlib.h>   
  4. #include <unistd.h>   
  5. #include <signal.h>   
  6. #include <pthread.h>   
  7.   
  8. int quitflag;  
  9. sigset_t mask;  
  10.   
  11. pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;  
  12. pthread_cond_t wait = PTHREAD_COND_INITIALIZER;  
  13.   
  14. void *thr_fn(void *arg)  
  15. {  
  16.     int signo;  
  17.     while(1)  
  18.     {  
  19.         //设置阻塞信号集   
  20.         sigwait(&mask, &signo);  
  21.         switch(signo)  
  22.         {  
  23.             //收到中断信号以后   
  24.         case SIGINT:  
  25.             printf("\ninterrupt\n");  
  26.             break;  
  27.   
  28.             //收到退出信号以后   
  29.         case SIGQUIT:  
  30.             pthread_mutex_lock(&lock);  
  31.             quitflag = 1;  
  32.             pthread_mutex_unlock(&lock);  
  33.             pthread_cond_signal(&wait);  
  34.             return 0;  
  35.   
  36.         default:  
  37.             printf("unexpected signal %d\n", signo);  
  38.             exit(1);  
  39.         }  
  40.     }  
  41. }  
  42.   
  43. int main(void)  
  44. {  
  45.     sigset_t oldmask;  
  46.     pthread_t tid;  
  47.   
  48.     sigemptyset(&mask);  
  49.     sigaddset(&mask, SIGINT);  
  50.     sigaddset(&mask, SIGQUIT);  
  51.   
  52.     pthread_sigmask(SIG_BLOCK, &mask, &oldmask);  
  53.     pthread_create(&tid, NULL, thr_fn, 0);  
  54.   
  55.     /* 
  56.     经典的UNIX条件锁三步曲: 
  57.     1。使用pthread_cond_wait前要先加锁 
  58.     2。pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活 
  59.     3。pthread_cond_wait被激活后会再自动加锁 
  60.     (所以还要我们视情况而决定是否手动解锁) 
  61.     */  
  62.     pthread_mutex_lock(&lock);  
  63.     while( 0 == quitflag )  
  64.         pthread_cond_wait(&wait, &lock);  
  65.     pthread_mutex_unlock(&lock);  
  66.   
  67.     //收到退出信号,但现在这个信号是阻塞的   
  68.     quitflag = 0;  
  69.     //重置阻塞信号集(让程序退出)   
  70.     sigprocmask(SIG_SETMASK, &oldmask, NULL);  
  71.     return 0;  
  72. }  

运行示例(红色字体的为输入):

www.bkjia.com @ubuntu:~/code$gcc temp.c -lpthread -o temp
www.bkjia.com @ubuntu:~/code$ ./temp
^C                              #输入中断字符(ctrl+C)
interrupt
^C                              #输入中断字符(ctrl+C)
interrupt
^C                              #输入中断字符(ctrl+C)
interrupt
^\                                #输入退出字符(ctrl+\)

相关内容