《Unix環境高級編程》這本書附帶了許多短小精美的小程序,我在閱讀此書的時候,將書上的代碼按照自己的理解重寫了一遍(大部分是抄書上的),加深一下自己的理解(純看書太困了,呵呵)。此例子在Ubuntu 10.04上測試通過。
相關鏈接
- 《UNIX環境高級編程》(第二版)apue.h的錯誤 http://www.linuxidc.com/Linux/2011-04/34662.htm
- Unix環境高級編程 源代碼地址 http://www.linuxidc.com/Linux/2011-04/34826.htm
程序簡介:在多線程程序中等侍信號設置標志,從而讓主程序退出。唯一可運行的控制線程應該是主線程和信號處理程序,所以阻塞信號足以避免錯失標志的修改。另外在線程中,需要使用互斥量來保護標志。以下這個程序演示了這方面的內容。
- //《APUE》程序12-6:同步信號處理
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <signal.h>
- #include <pthread.h>
-
- int quitflag;
- sigset_t mask;
-
- pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
- pthread_cond_t wait = PTHREAD_COND_INITIALIZER;
-
- void *thr_fn(void *arg)
- {
- int signo;
- while(1)
- {
- //設置阻塞信號集
- sigwait(&mask, &signo);
- switch(signo)
- {
- //收到中斷信號以後
- case SIGINT:
- printf("\ninterrupt\n");
- break;
-
- //收到退出信號以後
- case SIGQUIT:
- pthread_mutex_lock(&lock);
- quitflag = 1;
- pthread_mutex_unlock(&lock);
- pthread_cond_signal(&wait);
- return 0;
-
- default:
- printf("unexpected signal %d\n", signo);
- exit(1);
- }
- }
- }
-
- int main(void)
- {
- sigset_t oldmask;
- pthread_t tid;
-
- sigemptyset(&mask);
- sigaddset(&mask, SIGINT);
- sigaddset(&mask, SIGQUIT);
-
- pthread_sigmask(SIG_BLOCK, &mask, &oldmask);
- pthread_create(&tid, NULL, thr_fn, 0);
-
- /*
- 經典的UNIX條件鎖三步曲:
- 1。使用pthread_cond_wait前要先加鎖
- 2。pthread_cond_wait內部會解鎖,然後等待條件變量被其它線程激活
- 3。pthread_cond_wait被激活後會再自動加鎖
- (所以還要我們視情況而決定是否手動解鎖)
- */
- pthread_mutex_lock(&lock);
- while( 0 == quitflag )
- pthread_cond_wait(&wait, &lock);
- pthread_mutex_unlock(&lock);
-
- //收到退出信號,但現在這個信號是阻塞的
- quitflag = 0;
- //重置阻塞信號集(讓程序退出)
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
- return 0;
- }
運行示例(紅色字體的為輸入):
www.linuxidc.com @ubuntu:~/code$gcc temp.c -lpthread -o temp
www.linuxidc.com @ubuntu:~/code$ ./temp
^C #輸入中斷字符(ctrl+C)
interrupt
^C #輸入中斷字符(ctrl+C)
interrupt
^C #輸入中斷字符(ctrl+C)
interrupt
^\ #輸入退出字符(ctrl+\)