《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
程序簡介:在Unix環境下,我們可以讓程序屏蔽掉某些信號(SIGKILL信號和SIGSTOP除外),這個例子演示了這方面的功能。
- //《APUE》程序10-11:信號處理和sigprocmask實例
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <signal.h>
-
- //輸出錯誤信息並退出
- void error_quit(const char *str)
- {
- fprintf(stderr, "%s\n", str);
- exit(1);
- }
-
- //SIGQUIT信號的處理函數
- void sig_quit(int signo)
- {
- printf("caught SIGQUIT\n");
- if( SIG_ERR == signal(SIGQUIT, SIG_DFL) )
- error_quit("can't reset SIGQUIT");
- }
-
- int main(void)
- {
- sigset_t newmask, oldmask, pendmask;
- //設置對SIGQUIT信號的處理函數
- if( SIG_ERR == signal(SIGQUIT, sig_quit) )
- error_quit("can't catch SIGQUIT");
-
- //將newmask信號集初始化為空
- sigemptyset(&newmask);
- //在newmask信號集中增加SIGQUIT信號
- sigaddset(&newmask, SIGQUIT);
-
- int temp;
- //將oldmask設置為當前的屏蔽信號集(方便以後恢復)
- //在當前的屏蔽信號添加增加newmask信號集
- temp = sigprocmask(SIG_BLOCK, &newmask, &oldmask);
- if( temp < 0 )
- error_quit("SIG_BLOCK error");
-
- sleep(5);
-
- //返回當前的屏蔽信號集
- temp = sigpending(&pendmask);
- if( temp < 0 )
- error_quit("sigpending error");
- //檢查SIGQUIT信號是否在pendmask信號集中
- if( sigismember(&pendmask, SIGQUIT) )
- printf("\nSIGQUIT pending\n");
-
- //恢復屏蔽信號集
- temp = sigprocmask(SIG_SETMASK, &oldmask, NULL);
- if( temp < 0 )
- error_quit("SIG_SETMASK error");
- printf("SIGQUIT unblocked\n");
-
- sleep(5);
- return 0;
- }
運行示例:
www.linuxidc.com @ubuntu:~/code$ gcc temp.c -o temp
www.linuxidc.com @ubuntu:~/code$ ./temp
^\ #產生一次SIGQUIT信號
SIGQUIT pending #從sleep返回後
caught SIGQUIT #在信號處理程序中
SIGQUIT unblocked #從sigpromask返回後
^\退出 #再次產生信號
www.linuxidc.com @ubuntu:~/code$ ./temp #再次運行程序
^\^\^\^\^\^\^\^\^\^\^\^\ #產生多次SIGQUIT信號
SIGQUIT pending
caught SIGQUIT #只接收到一次信號
SIGQUIT unblocked
^\退出
結論:
1:進程阻塞了SIGQUIT信號,在此期間所產生的SIGQUIT信號都會被阻塞,直到該信號不再被阻塞。
2:在休眠期間,如果產生了信號,那麼此時的信號是未決的,但是不再受阻塞(所以在退出之前,sig_quit函數可以被調用)
3:在信號被阻塞期間系統不會對信號進行排隊。
注解(這段話是從網上摘抄的):
信號的”未決“是一種狀態,指的是從信號的產生到信號被處理前的這一段時間;信號的”阻塞“是一個開關動作,指的是阻止信號被處理,但不是阻止信號產生。
APUE例題在sleep前用sigprocmask阻塞了退出信號,然後sleep,然後在sleep的過程中產生一個退出信號,但是此時退出信號被阻塞過,(中文的”阻塞”在這裡容易被誤解為一種狀態,實際上是一種類似於開關的動作,所以說“被阻塞過”,而不是“被阻塞”)所以處於“未決”狀態,在 sleep後又用sigprocmask關掉退出信號的阻塞開關,因為之前產生的退出信號一直處於未決狀態,當關上���塞開關後,馬上退出“未決”狀態,得到處理,這一切發生在sigprocmask返回之前。