linux 信號signal和sigaction理解

轉載:http://blog.csdn.net/beginning1126/article/details/8680757

今天看到unp時發現之前對signal到理解實在淺顯,今天拿來單獨學習討論下。


signal,此函數相對簡單一些,給定一個信號,給出信號處理函數則可,當然,函數簡單,其功能也相對簡單許多,簡單給出個函數例子如下:

[cpp]?view plaincopy
  1. ?1?#include?<signal.h>??
  2. ?2?#include?<stdio.h>??
  3. ?3?#include?<unistd.h>??
  4. ?4???
  5. ?5?void?ouch(int?sig)??
  6. ?6?{??
  7. ?7?????printf("I?got?signal?%d\n",?sig);??
  8. ?8?????//?(void)?signal(SIGINT,?SIG_DFL);??
  9. ?9?????//(void)?signal(SIGINT,?ouch);??
  10. 10???
  11. 11?}??
  12. 12???
  13. 13???
  14. 14???
  15. 15?int?main()??
  16. 16?{??
  17. 17?????(void)?signal(SIGINT,?ouch);??
  18. 18???
  19. 19?????while(1)??
  20. 20?????{??
  21. 21?????????printf("hello?world...\n");??
  22. 22?????????sleep(1);??
  23. 23?????}??
  24. 24?}??
當然,實際運用中,需要對不同到signal設定不同的到信號處理函數,SIG_IGN忽略/SIG_DFL默認,這倆宏也可以作為信號處理函數。同時SIGSTOP/SIGKILL這倆信號無法捕獲和忽略。注意,經過實驗發現,signal函數也會堵塞當前正在處理的signal,但是沒有辦法阻塞其它signal,比如正在處理SIG_INT,再來一個SIG_INT則會堵塞,但是來SIG_QUIT則會被其中斷,如果SIG_QUIT有處理,則需要等待SIG_QUIT處理完了,SIG_INT才會接著剛才處理。


sigaction,這個相對麻煩一些,函數原型如下:

int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);

函數到關鍵就在于struct sigaction

[cpp]?view plaincopy
  1. stuct?sigaction??
  2. {??
  3. ??????void?(*)(int)?sa_handle;??
  4. ??????sigset_t?sa_mask;??
  5. ??????int?sa_flags;??
  6. }??

[cpp]?view plaincopy
  1. 1?#include?<signal.h>??
  2. ??2?#include?<stdio.h>??
  3. ??3?#include?<unistd.h>??
  4. ??4???
  5. ??5???
  6. ??6?void?ouch(int?sig)??
  7. ??7?{??
  8. ??8?????printf("oh,?got?a?signal?%d\n",?sig);??
  9. ??9???
  10. ?10?????int?i?=?0;??
  11. ?11?????for?(i?=?0;?i?<?5;?i++)??
  12. ?12?????{??
  13. ?13?????????printf("signal?func?%d\n",?i);??
  14. ?14?????????sleep(1);??
  15. ?15?????}??
  16. ?16?}??
  17. ?17???
  18. ?18???
  19. ?19?int?main()??
  20. ?20?{??
  21. ?21?????struct?sigaction?act;??
  22. ?22?????act.sa_handler?=?ouch;??
  23. ?23?????sigemptyset(&act.sa_mask);??
  24. ?24?????sigaddset(&act.sa_mask,?SIGQUIT);??
  25. ?25?????//?act.sa_flags?=?SA_RESETHAND;??
  26. ?26?????//?act.sa_flags?=?SA_NODEFER;??
  27. ?27?????act.sa_flags?=?0;??
  28. ?28???
  29. ?29?????sigaction(SIGINT,?&act,?0);??
  30. ?30???
  31. ?31???
  32. ?32?????struct?sigaction?act_2;??
  33. ?33?????act_2.sa_handler?=?ouch;??
  34. ?34?????sigemptyset(&act_2.sa_mask);??
  35. ?35?????act.sa_flags?=?0;??
  36. ?36?????sigaction(SIGQUIT,?&act_2,?0);??
  37. ?37???
  38. ????????while(1)??
  39. ????????{??
  40. ?????????????sleep(1);??
  41. ????????}??
  42. ?38?????return;??
  43. ??
  44. ????}??

1. 阻塞,sigaction函數有阻塞的功能,比如SIGINT信號來了,進入信號處理函數,默認情況下,在信號處理函數未完成之前,如果又來了一個SIGINT信號,其將被阻塞,只有信號處理函數處理完畢,才會對后來的SIGINT再進行處理,同時后續無論來多少個SIGINT,僅處理一個SIGINT,sigaction會對后續SIGINT進行排隊合并處理。

2. sa_mask,信號屏蔽集,可以通過函數sigemptyset/sigaddset等來清空和增加需要屏蔽的信號,上面代碼中,對信號SIGINT處理時,如果來信號SIGQUIT,其將被屏蔽,但是如果在處理SIGQUIT,來了SIGINT,則首先處理SIGINT,然后接著處理SIGQUIT。

3.?sa_flags如果取值為0,則表示默認行為。還可以取如下倆值,但是我沒覺得這倆值有啥用。

SA_NODEFER,如果設置來該標志,則不進行當前處理信號到阻塞

SA_RESETHAND,如果設置來該標志,則處理完當前信號后,將信號處理函數設置為SIG_DFL行為


下面單獨來討論一下信號屏蔽,記住是屏蔽,不是消除,就是來了信號,如果當前是block,則先不傳遞給當前進程,但是一旦unblock,則信號會重新到達。

[cpp]?view plaincopy
  1. #include?<signal.h>??
  2. #include?<stdio.h>??
  3. #include?<unistd.h>??
  4. ??
  5. ??
  6. ??
  7. static?void?sig_quit(int);??
  8. ??
  9. int?main?(void)?{??
  10. ????sigset_t?new,?old,?pend;??
  11. ??????
  12. ????signal(SIGQUIT,?sig_quit);??
  13. ??
  14. ????sigemptyset(&new);??
  15. ????sigaddset(&new,?SIGQUIT);??
  16. ????sigprocmask(SIG_BLOCK,?&new,?&old);??
  17. ??
  18. ????sleep(5);??
  19. ??
  20. ????printf("SIGQUIT?unblocked\n");??
  21. ????sigprocmask(SIG_SETMASK,?&old,?NULL);??
  22. ??
  23. ????sleep(50);??
  24. ????return?1;??
  25. }??
  26. ??
  27. static?void?sig_quit(int?signo)?{??
  28. ????printf("catch?SIGQUIT\n");??
  29. ????signal(SIGQUIT,?SIG_DFL);??
  30. }??

gcc -g -o mask mask.c?

./mask

========這個地方按多次ctrl+\

SIGQUIT unblocked

catch SIGQUIT
Quit (core dumped)

======================

注意觀察運行結果,在sleep的時候,按多次ctrl+\,由于sleep之前block了SIG_QUIT,所以無法獲得SIG_QUIT,但是一旦運行sigprocmask(SIG_SETMASK, &old, NULL);則unblock了SIG_QUIT,則之前發送的SIG_QUIT隨之而來。

由于信號處理函數中設置了DFL,所以再發送SIG_QUIT,則直接coredump。



本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384392.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384392.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384392.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux知識(二)互斥量、信號量和生產者消費者模型

linux知識&#xff08;二&#xff09;互斥量、信號量和生產者消費者模型一、互斥量產生原因二、信號量生產者消費者模型一、互斥量 產生原因 使用多線程常常會碰到數據混亂的問題&#xff0c;那么使用互斥量&#xff0c;相當于“加鎖”的操作&#xff0c;將有助于解決數據混亂…

基于Linux的Socket編程之TCP全雙工Server-Client聊天程序

轉載&#xff1a;http://blog.csdn.net/apollon_krj/article/details/53437764#0-tsina-1-58570-397232819ff9a47a7b7e80a40613cfe1 一、引言&#xff1a; 由于accept函數、read、write、recv、send等函數都是是阻塞式的&#xff0c;在同一個進程之中&#xff0c;只要有任何一個…

數據結構(一)線性表

數據結構&#xff08;一&#xff09;線性表一、線性表定義二、順序表定義動態數組三、單鏈表定義不帶頭結點帶頭結點頭結點與不帶頭結點的區別頭插法與尾插法雙鏈表循環鏈表循環單鏈表循環雙鏈表靜態鏈表一、線性表定義 線性表是具有相同數據類型的n個數據元素的有限序列 特點…

linux網絡編程(二)TCP通訊狀態

linux網絡編程&#xff08;二&#xff09;TCP通訊狀態TCP狀態轉換為什么需要等待2MSL&#xff1f;端口復用TCP狀態轉換 tcp協議連接開始會經過三次握手&#xff0c;客戶端和服務器開始都會處于CLOSED狀態 第一次握手&#xff1a;客戶端會先發送SYN請求給服務器&#xff0c;客戶…

gethostbyname() 函數說明

轉載&#xff1a;http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881611.html gethostbyname()函數說明——用域名或主機名獲取IP地址 包含頭文件 #include <netdb.h> #include <sys/socket.h> 函數原型 struct hostent *gethostbyna…

linux網絡編程(三)select、poll和epoll

linux網絡編程&#xff08;三&#xff09;select、poll和epoll一、為什么會有多路I/O轉接服務器&#xff1f;二、select三、poll三、epoll一、為什么會有多路I/O轉接服務器&#xff1f; 為什么會有多路I/O轉接服務器呢&#xff1f;在學這個之前&#xff0c;我們同使用的是多線…

Linux socket編程(一) 對套接字操作的封裝

轉載:http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html 以前寫的&#xff0c;現在回顧一下&#xff1a; 下面是對socket操作的封裝&#xff0c;因為在Linux下寫中文到了windows里面會亂碼&#xff0c;所以注釋用英文來寫&#xff0c;有空再查下解決方法吧 socket.…

數據結構(二)棧

棧一、棧順序棧線性棧(不帶頭結點)線性棧(帶頭結點)共享棧一、棧 棧是只允許在一端進行插入或刪除操作的線性表。 棧頂&#xff1a;線性表允許進行插入刪除的那一端 棧底&#xff1a;固定的&#xff0c;不允許進行插入和刪除的那一端 空棧&#xff1a;不含如何元素的空表 順序…

如何在linux上安裝sqlite數據庫

如何在linux上安裝sqlite數據庫一、下載二、解壓三、配置&#xff08;configure&#xff09;四、編譯和安裝五、執行sqlite3程序六、測試代碼一、下載 首先要先下載sqlite3源碼包 鏈接&#xff1a;https://pan.baidu.com/s/1_70342ZLlPjLlqGzpy5IHw 提取碼&#xff1a;84ne …

數據結構(三)隊列

數據結構&#xff08;三&#xff09;隊列隊列隊列&#xff08;順序存儲&#xff09;循環隊列&#xff08;順序存儲&#xff09;隊列&#xff08;鏈式存儲&#xff09;隊列 隊列是一種受限制的線性表&#xff0c;只允許表的一端插入&#xff0c;在表的另一端刪除 隊列&#xf…

Linux fcntl函數詳解

轉載&#xff1a;http://www.cnblogs.com/xuyh/p/3273082.html 功能描述&#xff1a;根據文件描述詞來操作文件的特性。 文件控制函數 fcntl -- file control 頭文件&#xff1a; #include <unistd.h> #include <fcntl.h> 函數原型&#xff1a; …

vs2019使用sqlite數據庫遠程連接linux

vs2019使用sqlite數據庫遠程連接linux一、sqlite3添加到目錄二、添加依賴庫三、測試一、sqlite3添加到目錄 將兩個sqlite3頭文件放入目錄中 二、添加依賴庫 打開項目屬性 添加完成 三、測試 #include <stdio.h> #include <sqlite3.h>int main(int argc, cha…

linux網絡編程(四)線程池

linux網絡編程&#xff08;四&#xff09;線程池為什么會有線程池&#xff1f;實現簡單的線程池為什么會有線程池&#xff1f; 大多數的服務器可能都有這樣一種情況&#xff0c;就是會在單位時間內接收到大量客戶端請求&#xff0c;我們可以采取接受到客戶端請求創建一個線程的…

AIGC:大語言模型LLM的幻覺問題

引言 在使用ChatGPT或者其他大模型時&#xff0c;我們經常會遇到模型答非所問、知識錯誤、甚至自相矛盾的問題。 雖然大語言模型&#xff08;LLMs&#xff09;在各種下游任務中展示出了卓越的能力&#xff0c;在多個領域有廣泛應用&#xff0c;但存在著幻覺的問題&#xff1a…

關于C++子類父類成員函數的覆蓋和隱藏

轉載&#xff1a;http://blog.csdn.net/worldmakewayfordream/article/details/46827161 函數的覆蓋 覆蓋發生的條件&#xff1a; &#xff08;1&#xff09; 基類必須是虛函數&#xff08;使用virtual 關鍵字來進行聲明&#xff09; &#xff08;2&#xff09;發生覆蓋的兩個函…

數據結構(四)串的順序存儲

#include <stdio.h> #include <stdlib.h>#define MAXLEN 255 //定長順序存儲 typedef struct {char ch[MAXLEN]; //每個分量存儲一個字符int length; //串的實際長度 }SString;//串的初始化 bool StrAssign(SString& T, char* chars) {int i 0, len;char* …

數據結構(四)串的動態數組存儲

#include <stdio.h> #include <stdlib.h>#define MAXLEN 255 //定長順序存儲 typedef struct {char* ch; //每個分量存儲一個字符int length; //串的實際長度 }SString;//串的初始化 bool StrAssign(SString& T, char* chars) {int i 0, len;T.ch (char*)m…

C++名字隱藏

轉載&#xff1a;http://www.weixueyuan.net/view/6361.html 如果派生類中新增一個成員變量&#xff0c;該成員變量與基類中的成員變量同名&#xff0c;則新增的成員變量就會遮蔽從基類中繼承過來的成員變量。同理&#xff0c;如果派生類中新增的成員函數與基類中的成員函數同…

c語言深入淺出(一)strcpy和memcpy的區別

c語言深入淺出&#xff08;一&#xff09;strcpy和memcpy的區別strcpy和memcpy都是c語言的庫函數 strcpy:只用于字符串的復制&#xff0c;當碰到‘\0’就停止了 memcpy:用于這個內存的拷貝&#xff0c;適用于結構體、字符數組、類等 char * strcpy(char * dest, const char * s…

C++ dynamic_cast操作符

轉載&#xff1a;http://www.weixueyuan.net/view/6377.html 在C中&#xff0c;編譯期的類型轉換有可能會在運行時出現錯誤&#xff0c;特別是涉及到類對象的指針或引用操作時&#xff0c;更容易產生錯誤。Dynamic_cast操作符則可以在運行期對可能產生問題的類型轉換進行測試。…