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

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux C: 信号及异常和捕捉函数原理

發(fā)布時(shí)間:2024/10/14 linux 76 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux C: 信号及异常和捕捉函数原理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
#define SIGHUP 1終端掛起或控制進(jìn)程終止
#define SIGINT 2終端中斷(Ctrl+C 組合鍵)
#define SIGQUIT 3終端退出(Ctrl+\組合鍵)
#define SIGILL 4非法指令
#define SIGTRAP 5debug 使用,有斷點(diǎn)指令產(chǎn)生
#define SIGABRT 6由 abort(3)發(fā)出的退出指令
#define SIGIOT 6IOT 指令
#define SIGBUS 7總線(xiàn)錯(cuò)誤
#define SIGFPE 8浮點(diǎn)運(yùn)算錯(cuò)誤
#define SIGKILL 9殺死、終止進(jìn)程
#define SIGUSR1 10用戶(hù)自定義信號(hào) 1
#define SIGSEGV 11段錯(cuò)誤(無(wú)效的內(nèi)存段)
#define SIGUSR2 12用戶(hù)自定義信號(hào) 2
#define SIGPIPE 13向非讀管道寫(xiě)入數(shù)據(jù)
#define SIGALRM 14鬧鐘
#define SIGTERM 15軟件終止
#define SIGSTKFLT 16棧異常
#define SIGCHLD 17子進(jìn)程結(jié)束
#define SIGCONT 18進(jìn)程繼續(xù)
#define SIGSTOP 19停止進(jìn)程的執(zhí)行,只是暫停
#define SIGTSTP 20停止進(jìn)程的運(yùn)行(Ctrl+Z 組合鍵)
#define SIGTTIN 21后臺(tái)進(jìn)程需要從終端讀取數(shù)據(jù)
#define SIGTTOU 22后臺(tái)進(jìn)程需要向終端寫(xiě)數(shù)據(jù)
#define SIGURG 23有"緊急"數(shù)據(jù)
#define SIGXCPU 24超過(guò) CPU 資源限制
#define SIGXFSZ 25文件大小超額
#define SIGVTALRM 26虛擬時(shí)鐘信號(hào)
#define SIGPROF 27時(shí)鐘信號(hào)描述
#define SIGWINCH 28窗口大小改變
#define SIGIO 29可以進(jìn)行輸入/輸出操作
#define SIGPOLLSIGIO
#define SIGPWR 30斷點(diǎn)重啟
#define SIGSYS 31非法的系統(tǒng)調(diào)用
#define SIGUNUSED 32未使用信號(hào)

轉(zhuǎn)載:「一只青木呀」的原創(chuàng)文章,原文鏈接:https://blog.csdn.net/weixin_45309916/article/details/111939072

一、信號(hào)和中斷
?

? ? ? ?信號(hào)是進(jìn)程間通信的重要內(nèi)容之一。它可以來(lái)源于硬件,例如鍵盤(pán)的 Ctrl+C 組合鍵,間隔定時(shí)器,IO錯(cuò)誤等硬件錯(cuò)誤;也可以是來(lái)源于自己,例如自己的代碼除0,指針越界等執(zhí)行報(bào)錯(cuò);其中最需要了解的是來(lái)自于其他進(jìn)程例如 kill命令。信號(hào)可以被捕捉從而觸發(fā)信號(hào)處理函數(shù)。信號(hào)處理函數(shù)可以被重寫(xiě),信號(hào)也可以被屏蔽。

? ? ? ? 在進(jìn)程結(jié)構(gòu)體PROC 中,都有一個(gè)信號(hào)處理數(shù)組 int sig[32] ; 其中值為0 代表默認(rèn)處理,1代表忽略,其他非零值表示用戶(hù)模式下預(yù)先設(shè)定好的信號(hào)處理函數(shù)地址。除了信號(hào)處理數(shù)組每個(gè)PROC都有一個(gè)32位向量(信號(hào)位向量) 和Mask(屏蔽)位向量? 。 bits向量用來(lái)指明哪些信號(hào)被signal? , masks 用來(lái)指明哪些信號(hào)被Block 。當(dāng)信號(hào)位為1時(shí),且屏蔽位為0時(shí),信號(hào)才會(huì)生效并傳遞給進(jìn)程。如果進(jìn)程發(fā)現(xiàn)了個(gè)未被阻塞的信號(hào),則會(huì)將信號(hào)位清0。

二、信號(hào)的捕捉和捕捉函數(shù)的設(shè)置?

? ? ? ? 信號(hào)處理內(nèi)容可以被修改,除了 SIGKILL(9)? 和 SIGSTOP(19)? 。 為了處理信號(hào)捕捉可能造成的死循環(huán),這兩個(gè)信號(hào)9和19作為終止進(jìn)程的最后手段,規(guī)定了不能被修改。

? ? ? ?進(jìn)程可以使用系統(tǒng)調(diào)用來(lái)修改捕捉到信號(hào)時(shí)的信號(hào)處理函數(shù):

? ? ? int r = signal (int signal_number , void *handler) ;?

? ? ?但是signal 函數(shù)有幾個(gè)個(gè)缺點(diǎn):

? ? 1。如果信號(hào)觸發(fā)頻率過(guò)快,可能導(dǎo)致下一個(gè)信號(hào)和信號(hào)處理函數(shù)重新設(shè)置會(huì)出現(xiàn)競(jìng)態(tài)條件。相同的,signal是線(xiàn)程不安全的,可能不適用于多線(xiàn)程。

? ? 2.? signal不能阻塞其他信號(hào),只能通過(guò)sigprocmask()來(lái)顯示屏蔽或者接觸屏蔽信號(hào)

? ? 3.signal 只能傳輸一個(gè)信號(hào)編號(hào),不能夠傳輸關(guān)于信號(hào)的其他信息?

因此,現(xiàn)在大多數(shù)都用sigaction()? 來(lái)代替 signal:

sigaction()? 的系統(tǒng)調(diào)用和 sigaction 結(jié)構(gòu)體如下:

int sigaction(int sigid ,const struct sigaction *act , struct sigaction *oldact );struct sigaction{ void (*sa_handler)(int); void (*sa_sigaction)(int , siginfo_t *,void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(int); }

sa_handler : 指向處理函數(shù)的指針

sa_sigaction :另一種方法,指向處理函數(shù)的指針 , 外加上了兩個(gè)額外的參數(shù)。其中siginfo_t 接收信號(hào)的更多信息。

sa_mask? ?: 在處理函數(shù)執(zhí)行時(shí),設(shè)置要阻塞的信號(hào)

sa_flags ;? ? 設(shè)置信號(hào)處理過(guò)程的行為,如果用sa_sigaction處理函數(shù),sa_flags 需設(shè)置為 SA_SIGINFO.

sigaction:的示例:

#include <stdio.h> #include <unistd.h> #include <signal.h> #include <string.h> void handler (int sig ,siginfo_t *siginfo , void * context){printf("handler:sig = %d from PID=%d UID=%d \n",sig,siginfo->si_pid,siginfo->si_uid); }int main(int argc, char * argv[]){struct sigaction act ;memset(&act ,0 ,sizeof(act));act.sa_sigaction = &handler ;act.sa_flags =SA_SIGINFO ;sigaction(SIGTERM,&act ,NULL);printf("looping\n");printf("enter kill PID=%d to send SIGTERM signal to it \n" , getpid());while(1){sleep(10);} }

上面的代碼利用sigaction 重新設(shè)置SIGTERM (15) 信號(hào),當(dāng)收到 15信號(hào)時(shí)就會(huì)執(zhí)行 handler內(nèi)容。開(kāi)啟另一個(gè)會(huì)話(huà)對(duì)進(jìn)程發(fā)出kill命令,則會(huì)有上面的輸出結(jié)果。最后發(fā)出的8信號(hào)對(duì)應(yīng)是浮點(diǎn)異常信號(hào),雖然上述程序并不會(huì)出現(xiàn)浮點(diǎn)異常,但是由于程序收到了該信號(hào),就執(zhí)行默認(rèn)的信號(hào)8處理函數(shù)了.

三、利用sigaction和管道實(shí)現(xiàn)消息IPC

Linux 管道和和文件描述符的相關(guān)內(nèi)容:可看

https://blog.csdn.net/superSmart_Dong/article/details/118641774

/****sigaction*****/ #include <stdio.h> #include <fcntl.h> #include <string.h> #include <signal.h>#define LEN 64 int ppipe[2]; //管道-文件描述符 int pid ; char line[LEN]; int parent(){printf("parent %d running \n",getpid());close(ppipe[0]); // 關(guān)閉標(biāo)準(zhǔn)輸入文件描述符while(1){printf("parent %d : input a line : \n" ,getpid());fgets(line ,LEN,stdin); // line[LEN]得到標(biāo)準(zhǔn)輸入line[strlen(line) -1 ] = 0 ;printf("parent %d write to pipe",getpid());write(ppipe[1],line,LEN); //向管道寫(xiě)入內(nèi)容printf("parent %d send signal 10 to %d",getpid(),pid);kill(pid,SIGUSR1);} } void chandler(int sig){printf ("\n child %d got an interrupt sig=%d \n ",getpid(),sig);read(ppipe[0] ,line ,LEN); //向管道讀出內(nèi)容 printf("child %d get a message = %s \n" ,getpid(),line); } int child(){char msg[LEN];int parent =getppid();printf("child %d running \n",getpid());close(ppipe[1]);signal(SIGUSR1,chandler);while(1); } int main(int argc, char * argv[]){pipe(ppipe);pid = fork();if (pid){parent();}else{child();} }

?

?

?

總結(jié)

以上是生活随笔為你收集整理的Linux C: 信号及异常和捕捉函数原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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