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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

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

轉載:「一只青木呀」的原創文章,原文鏈接:https://blog.csdn.net/weixin_45309916/article/details/111939072

一、信號和中斷
?

? ? ? ?信號是進程間通信的重要內容之一。它可以來源于硬件,例如鍵盤的 Ctrl+C 組合鍵,間隔定時器,IO錯誤等硬件錯誤;也可以是來源于自己,例如自己的代碼除0,指針越界等執行報錯;其中最需要了解的是來自于其他進程例如 kill命令。信號可以被捕捉從而觸發信號處理函數。信號處理函數可以被重寫,信號也可以被屏蔽。

? ? ? ? 在進程結構體PROC 中,都有一個信號處理數組 int sig[32] ; 其中值為0 代表默認處理,1代表忽略,其他非零值表示用戶模式下預先設定好的信號處理函數地址。除了信號處理數組每個PROC都有一個32位向量(信號位向量) 和Mask(屏蔽)位向量? 。 bits向量用來指明哪些信號被signal? , masks 用來指明哪些信號被Block 。當信號位為1時,且屏蔽位為0時,信號才會生效并傳遞給進程。如果進程發現了個未被阻塞的信號,則會將信號位清0。

二、信號的捕捉和捕捉函數的設置?

? ? ? ? 信號處理內容可以被修改,除了 SIGKILL(9)? 和 SIGSTOP(19)? 。 為了處理信號捕捉可能造成的死循環,這兩個信號9和19作為終止進程的最后手段,規定了不能被修改。

? ? ? ?進程可以使用系統調用來修改捕捉到信號時的信號處理函數:

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

? ? ?但是signal 函數有幾個個缺點:

? ? 1。如果信號觸發頻率過快,可能導致下一個信號和信號處理函數重新設置會出現競態條件。相同的,signal是線程不安全的,可能不適用于多線程。

? ? 2.? signal不能阻塞其他信號,只能通過sigprocmask()來顯示屏蔽或者接觸屏蔽信號

? ? 3.signal 只能傳輸一個信號編號,不能夠傳輸關于信號的其他信息?

因此,現在大多數都用sigaction()? 來代替 signal:

sigaction()? 的系統調用和 sigaction 結構體如下:

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 : 指向處理函數的指針

sa_sigaction :另一種方法,指向處理函數的指針 , 外加上了兩個額外的參數。其中siginfo_t 接收信號的更多信息。

sa_mask? ?: 在處理函數執行時,設置要阻塞的信號

sa_flags ;? ? 設置信號處理過程的行為,如果用sa_sigaction處理函數,sa_flags 需設置為 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 重新設置SIGTERM (15) 信號,當收到 15信號時就會執行 handler內容。開啟另一個會話對進程發出kill命令,則會有上面的輸出結果。最后發出的8信號對應是浮點異常信號,雖然上述程序并不會出現浮點異常,但是由于程序收到了該信號,就執行默認的信號8處理函數了.

三、利用sigaction和管道實現消息IPC

Linux 管道和和文件描述符的相關內容:可看

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]); // 關閉標準輸入文件描述符while(1){printf("parent %d : input a line : \n" ,getpid());fgets(line ,LEN,stdin); // line[LEN]得到標準輸入line[strlen(line) -1 ] = 0 ;printf("parent %d write to pipe",getpid());write(ppipe[1],line,LEN); //向管道寫入內容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); //向管道讀出內容 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();} }

?

?

?

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。