日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

信号捕捉(signal、sigaction)

發(fā)布時間:2023/11/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信号捕捉(signal、sigaction) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

信號的基本屬性:軟中斷,由內(nèi)核發(fā)送,內(nèi)核處理。某個進(jìn)程通過內(nèi)核向另一個進(jìn)程發(fā)送信號時(引起信號產(chǎn)生的五個因素),另一個進(jìn)程將會陷入內(nèi)核進(jìn)行中斷處理,未決信號集中相應(yīng)信號置1,當(dāng)遞達(dá)后,置0。如果阻塞信號集相應(yīng)信號為1,則該信號處于未決狀態(tài)。處于未決狀態(tài)中的信號,多次發(fā)送時,只是執(zhí)行一次,因?yàn)樵谖礇Q信號集中只是記錄了該信號的狀態(tài),沒有記錄發(fā)送的次數(shù)。信號抵達(dá)后,內(nèi)核進(jìn)行處理。處理方式有三:默認(rèn)處理方式(5種);忽略(丟棄)和捕捉。下面說明捕捉機(jī)制。

signal和sigaction函數(shù)只是完成對一個信號進(jìn)行注冊的功能,而對信號的捕捉的處理都是由內(nèi)核完成的。當(dāng)對一個信號進(jìn)行注冊后,內(nèi)核對其捕捉同時調(diào)用其注冊時對應(yīng)的用戶處理函數(shù)。

1signal函數(shù)

typedef void (*sighandler_t)(int);? //定義一個函數(shù)類型 sighandler_t

sighandler_t signal(int signum, sighandler_t handler);

作用:注冊一個信號捕捉函數(shù)

返回值:成功返回sighandler_t類型的函數(shù)(或函數(shù)首地址);失敗則返回一個宏:SIG_ERR。注意判斷該函數(shù)的返回值: sighandler ret = signal(·······);if(ret==SIG_ERR)

第一個參數(shù)為信號;第二個參數(shù)為sighandler_t類型函數(shù)(即返回值為void,形參為int)。

注意:該函數(shù)由ANSI定義,由于歷史原因在不同版本的Unix和不同版本的Linux中可能有不同的行為。因此應(yīng)該盡量避免使用它,取而代之使用sigaction函數(shù)。

#include <signal.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <unistd.h>typedef void (*sighandler_t) (int); //定義sighandler_t類型void catchsigint(int signo) {printf("-----------------catch\n"); }int main(void) {sighandler_t handler;handler = signal(SIGINT, catchsigint); //注冊2號信號if (handler == SIG_ERR) {perror("signal error");exit(1);} //判斷返回值while (1);return 0; }

[root@localhost 01_signal_test]# ./signal2

^C-----------------catch???????????????? //Ctrl+C?

^C-----------------catch??????????? ?????//Ctrl+C?

^\Quit (core dumped) ????????????????//Ctrl+\

只要一發(fā)送2號信號,就會執(zhí)行相應(yīng)函數(shù)。

2sigaction函數(shù)

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);?

作用:對某個信號進(jìn)行注冊(同signal),即對某個信號之前對應(yīng)的處理方式(函數(shù))進(jìn)行修改。

返回值:成功0;失敗-1,設(shè)置errno。

參數(shù):

act傳入?yún)?shù),新的處理方式。

oldact傳出參數(shù),舊的處理方式。

struct sigaction結(jié)構(gòu)體:

??? struct sigaction {

?????? ?void??? ?(*sa_handler)(int);

??????? void???? (*sa_sigaction)(int, siginfo_t *, void *);

????? ??sigset_t?? sa_mask;

??????? int?????? sa_flags;

?????? ?void???? (*sa_restorer)(void);

??? };? ?//最后一個成員不用(舍棄了);第二成員不常用

sa_restorer:該元素是過時的,不應(yīng)該使用,POSIX.1標(biāo)準(zhǔn)將不指定該元素。(棄用)

sa_sigaction:當(dāng)sa_flags被指定為SA_SIGINFO標(biāo)志時,使用該信號處理程序。(很少使用)?

重點(diǎn)掌握:

sa_handler:指定信號捕捉后的處理函數(shù)名(即注冊函數(shù))。也可賦值為SIG_IGN表忽略 SIG_DFL表執(zhí)行默認(rèn)動作;

sa_mask: 調(diào)用信號處理函數(shù)時,所要屏蔽的信號集合(信號屏蔽字)。注意:僅在處理函數(shù)被調(diào)用期間屏蔽生效,是臨時性設(shè)置;sa_mask也是一個字(64位),只是在執(zhí)行相應(yīng)的用戶處理函數(shù)期間生效。即在執(zhí)行用戶處理函數(shù)期間, sa_mask屏蔽的信號也不能遞達(dá),處于未決狀態(tài)。如果sa_mask未屏蔽,則響應(yīng)信號,中斷嵌套。相當(dāng)于此期間,sa_mask代替了mask。

sa_flags:通常設(shè)置為0,表示用默認(rèn)屬性。默認(rèn)屬性即為:sa_mask中將自己屏蔽,即該信號的注冊函數(shù)執(zhí)行期間,再次向進(jìn)程發(fā)送該信號,該信號不能遞達(dá),處于未決狀態(tài)。

最后一個參數(shù)如果不關(guān)心之前的處理方式,可以為NULL

3)信號捕捉機(jī)制

進(jìn)程正常運(yùn)行時,默認(rèn)PCB中有一個信號屏蔽字,假定為mask,它決定了進(jìn)程自動屏蔽哪些信號。當(dāng)注冊了某個信號捕捉函數(shù),捕捉到該信號以后,要調(diào)用該函數(shù)。而該函數(shù)有可能執(zhí)行很長時間,在這期間所屏蔽的信號不由mask來指定。而是用sa_mask來指定。調(diào)用完信號處理函數(shù),再恢復(fù)為mask。

sa_flags為0時,XXX信號捕捉函數(shù)執(zhí)行期間,XXX信號自動被屏蔽。

阻塞的常規(guī)信號(1-31)不支持排隊(duì),產(chǎn)生多次只記錄一次。(后32個實(shí)時信號支持排隊(duì))

內(nèi)核實(shí)現(xiàn)信號捕捉的過程如下:

首先,處于用戶態(tài)(user mode)的某個進(jìn)程在執(zhí)行到某個指令時突然接收某個信號(軟中斷,終端按鍵產(chǎn)生;硬件異常產(chǎn)生;命令產(chǎn)生;系統(tǒng)調(diào)用產(chǎn)生或者軟件條件產(chǎn)生),會暫停執(zhí)行下一條指令而陷入內(nèi)核進(jìn)入內(nèi)核態(tài)。

內(nèi)核在處理這一異常后,在準(zhǔn)備會用戶態(tài)之前先處理可以遞達(dá)該進(jìn)程的信號。

如果該信號的處理方式為捕捉,則內(nèi)核對該信號進(jìn)行捕捉,同時調(diào)用相應(yīng)的用戶處理函數(shù),回到用戶態(tài)執(zhí)行相應(yīng)的用戶處理函數(shù)(注意不是回到主控制流程)。

在用戶處理函數(shù)執(zhí)行完返回時,再次執(zhí)行系統(tǒng)調(diào)用sigretum再次進(jìn)入內(nèi)核。因?yàn)楹瘮?shù)執(zhí)行完需要返回到該函數(shù)的調(diào)用點(diǎn),而該函數(shù)是內(nèi)核調(diào)用的,因此需要再次返回到內(nèi)核。

最后,從內(nèi)核再次返回到用戶模式,從上次中斷處繼續(xù)執(zhí)行下一條指令。

?

//練習(xí)1:為某個信號設(shè)置捕捉函數(shù);驗(yàn)證在信號處理函數(shù)執(zhí)行期間,該信號多次遞送,那么只在處理函數(shù)之行結(jié)束后,處理一次;驗(yàn)證sa_mask在捕捉函數(shù)執(zhí)行期間的屏蔽作用。

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h>void docatch(int signo) //用戶處理函數(shù) {printf("the %dth signal is catched\n", signo);sleep(10); printf("-------finish------\n"); } int main(void) {int ret;struct sigaction act;act.sa_handler = docatch;sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask, SIGQUIT); //sa_mask屏蔽字中,3號信號置1act.sa_flags = 0; //默認(rèn)屬性 信號捕捉函數(shù)執(zhí)行期間,自動屏蔽本信號ret = sigaction(SIGINT, &act, NULL); //注冊2號信號if (ret == -1) {perror("sigaction error");exit(1);}while (1);return 0; }

[root@localhost 01_signal_test]# ./test_sigac

^Cthe 2th signal is catched ??// 發(fā)2號信號 Ctrl +C

-------finish------

^Cthe 2th signal is catched ?// 發(fā)2號信號 Ctrl +C

^C^C^C^C^C^C^C^C^C^C^C^C^C-------finish------? ?// 執(zhí)行期間,發(fā)多個2號信號

the 2th signal is catched

-------finish------???????? ???//但是只是執(zhí)行了一次

^Cthe 2th signal is catched

^\^\^\^\^\^\^\^\^\^\^\^\-------finish------?? // 執(zhí)行期間,發(fā)多個3號信號

Quit (core dumped)?? //2號信號處理完后,處理2號,則退出進(jìn)程,結(jié)束。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的信号捕捉(signal、sigaction)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。