歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 《APUE》:信號處理

《APUE》:信號處理

日期:2017/3/1 10:10:24   编辑:Linux編程

《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除外),這個例子演示了這方面的功能。

  1. //《APUE》程序10-11:信號處理和sigprocmask實例
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <signal.h>
  6. //輸出錯誤信息並退出
  7. void error_quit(const char *str)
  8. {
  9. fprintf(stderr, "%s\n", str);
  10. exit(1);
  11. }
  12. //SIGQUIT信號的處理函數
  13. void sig_quit(int signo)
  14. {
  15. printf("caught SIGQUIT\n");
  16. if( SIG_ERR == signal(SIGQUIT, SIG_DFL) )
  17. error_quit("can't reset SIGQUIT");
  18. }
  19. int main(void)
  20. {
  21. sigset_t newmask, oldmask, pendmask;
  22. //設置對SIGQUIT信號的處理函數
  23. if( SIG_ERR == signal(SIGQUIT, sig_quit) )
  24. error_quit("can't catch SIGQUIT");
  25. //將newmask信號集初始化為空
  26. sigemptyset(&newmask);
  27. //在newmask信號集中增加SIGQUIT信號
  28. sigaddset(&newmask, SIGQUIT);
  29. int temp;
  30. //將oldmask設置為當前的屏蔽信號集(方便以後恢復)
  31. //在當前的屏蔽信號添加增加newmask信號集
  32. temp = sigprocmask(SIG_BLOCK, &newmask, &oldmask);
  33. if( temp < 0 )
  34. error_quit("SIG_BLOCK error");
  35. sleep(5);
  36. //返回當前的屏蔽信號集
  37. temp = sigpending(&pendmask);
  38. if( temp < 0 )
  39. error_quit("sigpending error");
  40. //檢查SIGQUIT信號是否在pendmask信號集中
  41. if( sigismember(&pendmask, SIGQUIT) )
  42. printf("\nSIGQUIT pending\n");
  43. //恢復屏蔽信號集
  44. temp = sigprocmask(SIG_SETMASK, &oldmask, NULL);
  45. if( temp < 0 )
  46. error_quit("SIG_SETMASK error");
  47. printf("SIGQUIT unblocked\n");
  48. sleep(5);
  49. return 0;
  50. }

運行示例:

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返回之前。

Copyright © Linux教程網 All Rights Reserved