函數sigsetjump和siglongjump

摘要:

  • 在信號處理函數執行時,會阻塞當前信號。
  • 當信號處理函數返回時,系統會幫我們把剛剛阻塞的信號再從阻塞集中移除。

?

一、 臨時阻塞特性

當執行信號處理函數的時候,會臨時將當前被處理信號阻塞。為了能說明問題,采用實驗來驗證。

下面這段程序在收到 SIGALRM 信號或者 SIGQUIT 信號時,會打印當前信號,同時打印當前被阻塞的信號。

測試代碼:

#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>void printBlock() {sigset_t block;sigprocmask(SIG_BLOCK, NULL, &block);printf("block:");if (sigismember(&block, SIGQUIT)) printf("SIGQUIT, ");if (sigismember(&block, SIGALRM)) printf("SIGALRM\t");puts("");
}void handler(int sig) {if (sig == SIGQUIT) printf("SIGQUIT, ");if (sig == SIGALRM) printf("SIGALRM, ");printBlock();puts("--------------------------------------------------");
}int main() {printf("I'm %d\n", getpid());signal(SIGQUIT, handler);signal(SIGALRM, handler);printf("before signal, ");printBlock();while (1) {pause();}return 0;
}

輸出結果:

結果分析:

可以看到當程序收到 SIGALRM 信號時,在信號處理函數中 SIGALRM 信號會被臨時阻塞;SIGQUIT 信號同理。

執行完畢再從阻塞信號集中移除我就不驗證了。實際上,你重復發送 SIGALRM 信號,信號處理函數都能正常執行就已經證明 SIGALRM 信號未被阻塞(當然了,如果你手速比 cpu 運行的還快,可能會有信號合并的情況,這種不在考慮之列)。
?

?

?

二、跳出你的信號處理函數?

試想一下,如果你在信號處理函數中使用 longjmp 跳走了,系統會不會幫你把臨時阻塞的信號給撤走?答案是,不會。這將導致程序 bug。從此以后,你的程序再也不能處理該信號了。空口無憑,用實驗說話。

下面這段程序,在信號處理函數中打印當前信號和當前被阻塞的信號。完成后沒有直接 return,而是使用 longjmp 跳轉到 setjmp 的位置。接下來再打印阻塞信號。

測試代碼:

#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>jmp_buf jmpbuf;void printBlock()
{sigset_t block;sigprocmask(SIG_BLOCK, NULL, &block);printf("block:");if (sigismember(&block, SIGQUIT)) printf("SIGQUIT, ");if (sigismember(&block, SIGALRM)) printf("SIGALRM");puts("");
}void handler(int sig)
{if (sig == SIGQUIT) printf("SIGQUIT, ");if (sig == SIGALRM) printf("SIGALRM, ");printBlock();longjmp(jmpbuf, 1);puts("--------------------------------------------------");
}int main()
{printf("I'm %d\n", getpid());signal(SIGQUIT, handler);signal(SIGALRM, handler);printf("before signal, ");printBlock();if (setjmp(jmpbuf) != 0) {printf("jump to here! ");printBlock();puts("====================================================");}while (1) {pause();}return 0;
}

?輸出結果:

結果分析:

可以看到,當 jump 到 main 函數中的時候,SIGQUIT 依然被阻塞了,SIGALRM 也是。此后,無論你再怎么發送這兩個信號,處理函數也不會執行了。因為這兩個信號沒有從阻塞集中刪除。

這是 bug。

解決方案是使用另外兩個函數,分別是 sigsetjmp 和 siglongjmp。所以,我們只要把上面代碼中的 setjmp 和 longjmp 分別替換成這兩個函數就行了。
?

?

三、函數sigsetjump和siglongjump應用

1. 測試代碼:

#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>jmp_buf jmpbuf;void printBlock() {sigset_t block;sigprocmask(SIG_BLOCK, NULL, &block);printf("block:");if (sigismember(&block, SIGQUIT)) printf("SIGQUIT, ");if (sigismember(&block, SIGALRM)) printf("SIGALRM");puts("");
}void handler(int sig) {if (sig == SIGQUIT) printf("SIGQUIT, ");if (sig == SIGALRM) printf("SIGALRM, ");printBlock();siglongjmp(jmpbuf, 1); puts("--------------------------------------------------");
}int main() {printf("I'm %d\n", getpid());signal(SIGQUIT, handler);signal(SIGALRM, handler);printf("before signal, ");printBlock();if (sigsetjmp(jmpbuf, 1) != 0) {printf("jump to here! ");printBlock();puts("====================================================");}while(1) {pause();}return 0;
}

輸出結果:?

?

四、參考資料?

1.?47-跳出信號處理函數

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

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

相關文章

java操作word文檔,深度解析,值得收藏

Java虛擬機內存模型 Java虛擬機內存模型中定義的訪問操作與物理計算機處理的基本一致&#xff01; Java中通過多線程機制使得多個任務同時執行處理&#xff0c;所有的線程共享JVM內存區域main memory&#xff0c;而每個線程又單獨的有自己的工作內存&#xff0c;當線程與內存區…

函數sigsuspend

1. 測試代碼&#xff1a; #include<stdio.h> #include<stdlib.h> #include<signal.h> #include<errno.h> #include<unistd.h>void catch_sigalrm(int signo) {; }unsigned int mysleep(unsigned int seconds) {struct sigaction newact, olda…

java支付模塊架構,漲薪7K!

Java基礎 JDK 和 JRE 有什么區別&#xff1f; 和 equals 的區別是什么&#xff1f;兩個對象的 hashCode()相同&#xff0c;則 equals()也一定為 true&#xff0c;對嗎&#xff1f;final 在 java 中有什么作用&#xff1f;java 中的 Math.round(-1.5) 等于多少&#xff1f;Stri…

【信號】SIGCHLD信號

一、SIGCHLD信號 1. SIGCHLD簡介 SIGCHLD的產生條件&#xff1a; 子進程終止子進程接收到SIGSTOP信號停止時子進程處于停止狀態&#xff0c;接收到SIGCONT后喚醒注意&#xff1a;通過signal(SIGCHLD, SIG_IGN)通知內核對子進程的結束不關心&#xff0c;由內核回收。如果不想讓…

java改錯題技巧,看這篇文章準沒錯!

阿里 mq 消息可靠性,冪等如何保證分布式鎖的實現方案比較,為什么選擇 zookeeper, zookeeper 一致性協議原理線程池參數,阻塞隊列實現一致性 Hash解決什么問題, 如何實現? 虛擬節點的作用?Java 鎖的實現方式, 比較? AQS實現原理?公平非公平實現原理?CAS 實現原理volatile 實…

函數stat、fstat、fstatat和lstat

一、主要函數應用 #include <sys/stat.h> int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf) int lstat(const char *path, struct stat *buf); int fstat(int fd, const char *path, struct stat *buf, int flag);參數&#xff1a;…

java教程pdf下載百度云,面試題+筆記+項目實戰

一面問題&#xff1a;MySQLRedisKafka線程算法 mysql知道哪些存儲引擎&#xff0c;它們的區別mysql索引在什么情況下會失效mysql在項目中的優化場景&#xff0c;慢查詢解決等mysql有什么索引&#xff0c;索引模型是什么B-樹與B樹的區別&#xff1f;為什么不用紅黑樹mysql主從同…

函數mkdir、mkdirat和emdir

一、目錄的權限位 目錄的權限位&#xff0c;至少要設置一個執行許可位。即 rwx 中的那個 x 位。如果不設置&#xff0c;就沒辦法使用 cd 命令進入目錄&#xff0c;也無法讀取目錄下的文件內容。所以&#xff0c;這個位是必須的。目錄的寫權限位。如果未設置寫權限位(w 位)&…

java教程傳智播客,面試真題解析

01 阿里中間件&#xff08;四面&#xff0c;Java崗&#xff09; 1.1 Java中間件一面 技術一面考察范圍 重點問了Java線程鎖&#xff1a;synchronized 和ReentrantLock相關的底層實現 線程池的底層實現以及常見的參數 數據結構基本都問了一遍&#xff1a;鏈表、隊列等 Java內存…

函數chdir和get

摘要&#xff1a; chdir 這個命令類似于 linux 的命令 cd&#xff0c;而 getcwd 有點像 pwd。 函數原型&#xff1a; #include <unistd.h> int chdir(const char *path); char *getcwd(char *buf, size_t size); 當前工作目錄 當前工作目錄是針對進程而言的&#xff0…

java教程百度文庫,成功拿到offer

正文 現在市面上的算法資料也五花八門&#xff0c;種類繁多&#xff0c;小編也整理了一份不同于市面且有意思的算法資料&#xff0c;不能說多全面&#xff0c;但是是小編花了很長時間整理歸納出來的&#xff0c;自我感覺還行。分享給同事及群里反響都不錯&#xff0c;所以小編…

link系列函數

摘要&#xff1a; 圖解符號鏈接和硬鏈接的區別和i節點的介紹 二、link函數 link 函數專門用來創建硬鏈接的&#xff0c;功能和 ln 命令一樣。它主要做兩件事&#xff1a;1) 創建一個目錄項 2) inode 結構體引用計數加 1。這兩步是一個原子操作&#xff0c;要么全部失敗&#…

java數字排序代碼,進階加薪全靠它!

數據庫 2.1 池化技術&#xff1a;如何減少頻繁創建數據庫連接的性能損耗&#xff1f;2.2 數據庫優化方案&#xff08;一&#xff09;&#xff1a;查詢請求增加時&#xff0c;如何做主從分離&#xff1f;2.3 數據庫優化方案&#xff08;二&#xff09;&#xff1a;寫入數據量增…

函數umask

umask函數原型&#xff1a; #include <sys/stat.h> mode_t umask(mode_t mask); 分析&#xff1a; 在進程創建一個新的文件或目錄時&#xff0c;如調用open函數創建一個新文件&#xff0c;新文件的實際存取權限是mode與umask按照 mode&~umask運算以后的結果。umask…

java數據分析庫,威力加強版

美團技術一面20分鐘 晚7點&#xff0c;因為想到下周一才面試&#xff0c;我剛準備出去打個羽毛球&#xff0c;北京的電話就來了。面試官各種抱歉&#xff0c;說開會拖延了。 1、自我介紹 說了很多遍了&#xff0c;很流暢撿重點介紹完。 2、問我數據結構算法好不好 挺好的&…

函數chown

一、chown 命令 下面以實例簡單講解下 chown 的使用方法。當前登錄的賬號是 sunbin 創建測試文件當前 test.txt 文件所有者是sunbin&#xff0c;所屬組也是sunbin。 利用 chown 命令修改 test.txt 的所有者和所屬組.可以看到&#xff0c;test.txt 的擁有者變成了 root&#…

不愧是Alibaba技術官,java數組實現單向鏈表

緩存雪崩 緩存雪崩指的是Redis當中的大量緩存在同一時間全部失效&#xff0c;而假如恰巧這一段時間同時又有大量請求被發起&#xff0c;那么就會造成請求直接訪問到數據庫&#xff0c;可能會把數據庫沖垮。 緩存雪崩一般形容的是緩存中沒有而數據庫中有的數據&#xff0c;而因…

【線程】讀寫鎖

一、概念 一把讀寫鎖具備三種狀態&#xff1a; 讀模式下加鎖狀態(讀鎖&#xff09;寫模式下加鎖轉態(寫鎖)不加鎖狀態2. 讀寫鎖特性&#xff1a; 讀寫鎖是寫模式加鎖時&#xff0c;解鎖前&#xff0c;所有對該鎖加鎖的線程都會阻塞。讀寫鎖是讀模式加鎖時&#xff0c;如果線程以…

不愧是阿里大佬,mysql存儲過程寫法案例

容器化時代來了 虛擬化技術已經走過了三個時代&#xff0c;沒有容器化技術的演進就不會有 Docker 技術的誕生。 虛擬化技術演進 &#xff08;1&#xff09;物理機時代&#xff1a;多個應用程序可能會跑在一臺機器上。 &#xff08;2&#xff09;虛擬機時代&#xff1a;一臺物…

讀寫鎖(二)

一、實驗項目 【問題描述】程序 trainticket 中&#xff0c;有 100 個線程&#xff0c;其中 90 個線程是查余票數量的&#xff0c;只有 10 個線程搶票&#xff0c;每個線程一次買 10 張票。初始狀態下一共有 1000 張票。因此執行完畢后&#xff0c;還會剩下 900 張票。 程序 …