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

歡迎訪問 生活随笔!

生活随笔

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

linux

linux c之信号signal处理机制

發布時間:2023/12/4 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux c之信号signal处理机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近同事的程序設計過程中用到了Linux的signal機制,從而引發了我對Linux中signal機制的思考。Signal機制在Linux中是一個非常常用的進程間通信機制,很多人在使用的時候不會考慮該機制是具體如何實現的。signal機制可以被理解成進程的軟中斷,因此,在實時性方面還是相對比較高的。Linux中signal機制的模型可以采用下圖進行描述。

個進程都會采用一個進程控制塊對其進行描述,進程控制塊中設計了一個signal的位圖信息,其中的每位與具體的signal相對應,這與中斷機制是保持一致的。當系統中一個進程A通過signal系統調用向進程B發送signal時,設置進程B的對應signal位圖,類似于觸發了signal對應中斷。發送signal只是“中斷”觸發的一個過程,具體執行會在兩個階段發生:

1、? system call返回。進程B由于調用了system call后,從內核返回用戶態時需要檢查他擁有的signal位圖信息表,此時是一個執行點。

2、? 中斷返回。進程被系統中斷打斷之后,系統將CPU交給進程時,需要檢查即將執行進程所擁有的signal位圖信息表,此時也是一個執行點。

?

綜上所述,signal的執行點可以理解成從內核態返回用戶態時,在返回時,如果發現待執行進程存在被觸發的signal,那么在離開內核態之后(也就是將CPU切換到用戶模式),執行用戶進程為該signal綁定的signal處理函數,從這一點上看,signal處理函數是在用戶進程上下文中執行的。當執行完signal處理函數之后,再返回到用戶進程被中斷或者system call(軟中斷或者指令陷阱)打斷的地方。

?

?????? Signal機制實現的比較靈活,用戶進程由于中斷或者system call陷入內核之后,將斷點信息都保存到了堆棧中,在內核返回用戶態時,如果存在被觸發的signal,那么直接將待執行的signal處理函數push到堆棧中,在CPU切換到用戶模式之后,直接pop堆棧就可以執行signal處理函數并且返回到用戶進程了。Signal處理函數應用了進程上下文,并且應用實際的中斷模擬了進程的軟中斷過程。

?

最近寫程序,各種bug各種錯,有一回程序莫名退出,沒報錯,也沒產生日志和core文件,貌似正常退出一樣。

但又不是在程序全部走完后退出,中途莫名退出,這就叫我想到了signal,應該是某些函數錯誤后發送kill信號給主進程,然后退出。

現在總結下signal各種類型:

Signal Description
SIGABRT 由調用abort函數產生,進程非正常退出
SIGALRM 用alarm函數設置的timer超時或setitimer函數設置的interval timer超時
SIGBUS 某種特定的硬件異常,通常由內存訪問引起
SIGCANCEL 由Solaris Thread Library內部使用,通常不會使用
SIGCHLD 進程Terminate或Stop的時候,SIGCHLD會發送給它的父進程。缺省情況下該Signal會被忽略
SIGCONT 當被stop的進程恢復運行的時候,自動發送
SIGEMT 和實現相關的硬件異常
SIGFPE 數學相關的異常,如被0除,浮點溢出,等等
SIGFREEZE Solaris專用,Hiberate或者Suspended時候發送
SIGHUP 發送給具有Terminal的Controlling Process,當terminal被disconnect時候發送
SIGILL 非法指令異常
SIGINFO BSD signal。由Status Key產生,通常是CTRL+T。發送給所有Foreground Group的進程
SIGINT 由Interrupt Key產生,通常是CTRL+C或者DELETE。發送給所有ForeGround Group的進程
SIGIO 異步IO事件
SIGIOT 實現相關的硬件異常,一般對應SIGABRT
SIGKILL 無法處理和忽略。中止某個進程
SIGLWP 由Solaris Thread Libray內部使用
SIGPIPE 在reader中止之后寫Pipe的時候發送
SIGPOLL 當某個事件發送給Pollable Device的時候發送
SIGPROF Setitimer指定的Profiling Interval Timer所產生
SIGPWR 和系統相關。和UPS相關。
SIGQUIT 輸入Quit Key的時候(CTRL+\)發送給所有Foreground Group的進程
SIGSEGV 非法內存訪問
SIGSTKFLT Linux專用,數學協處理器的棧異常
SIGSTOP 中止進程。無法處理和忽略。
SIGSYS 非法系統調用
SIGTERM 請求中止進程,kill命令缺省發送
SIGTHAW Solaris專用,從Suspend恢復時候發送
SIGTRAP 實現相關的硬件異常。一般是調試異常
SIGTSTP Suspend Key,一般是Ctrl+Z。發送給所有Foreground Group的進程
SIGTTIN 當Background Group的進程嘗試讀取Terminal的時候發送
SIGTTOU 當Background Group的進程嘗試寫Terminal的時候發送
SIGURG 當out-of-band data接收的時候可能發送
SIGUSR1 用戶自定義signal 1
SIGUSR2 用戶自定義signal 2
SIGVTALRM setitimer函數設置的Virtual Interval Timer超時的時候
SIGWAITING Solaris Thread Library內部實現專用
SIGWINCH 當Terminal的窗口大小改變的時候,發送給Foreground Group的所有進程
SIGXCPU 當CPU時間限制超時的時候
SIGXFSZ 進程超過文件大小限制
SIGXRES Solaris專用,進程超過資源限制的時候發送

signal對應的值:

POSIX.1中列出的信號:

SIGHUP 1 A 終端掛起或者控制進程終止?
SIGINT 2 A 鍵盤中斷(如break鍵被按下)?
SIGQUIT 3 C 鍵盤的退出鍵被按下?
SIGILL 4 C 非法指令?
SIGABRT 6 C 由abort(3)發出的退出指令?
SIGFPE 8 C 浮點異常?
SIGKILL 9 AEF Kill信號?
SIGSEGV 11 C 無效的內存引用?
SIGPIPE 13 A 管道破裂: 寫一個沒有讀端口的管道?
SIGALRM 14 A 由alarm(2)發出的信號?
SIGTERM 15 A 終止信號?
SIGUSR1 30,10,16 A 用戶自定義信號1?
SIGUSR2 31,12,17 A 用戶自定義信號2?
SIGCHLD 20,17,18 B 子進程結束信號?
SIGCONT 19,18,25 進程繼續(曾被停止的進程)?
SIGSTOP 17,19,23 DEF 終止進程?
SIGTSTP 18,20,24 D 控制終端(tty)上按下停止鍵?
SIGTTIN 21,21,26 D 后臺進程企圖從控制終端讀?
SIGTTOU 22,22,27 D 后臺進程企圖從控制終端寫?

沒在POSIX.1中列出,而在SUSv2列出

SIGBUS 10,7,10 C 總線錯誤(錯誤的內存訪問)?
SIGPOLL A Sys V定義的Pollable事件,與SIGIO同義?
SIGPROF 27,27,29 A Profiling定時器到?
SIGSYS 12,-,12 C 無效的系統調用 (SVID)?
SIGTRAP 5 C 跟蹤/斷點捕獲?
SIGURG 16,23,21 B Socket出現緊急條件(4.2 BSD)?
SIGVTALRM 26,26,28 A 實際時間報警時鐘信號(4.2 BSD)?
SIGXCPU 24,24,30 C 超出設定的CPU時間限制(4.2 BSD)?
SIGXFSZ 25,25,31 C 超出設定的文件大小限制(4.2 BSD)?

(對于SIGSYS,SIGXCPU,SIGXFSZ,以及某些機器體系結構下的SIGBUS,Linux缺省的動作是A (terminate),SUSv2 是C (terminate and dump core))。?

下面是其它的一些信號?

信號 值 處理動作 發出信號的原因?
----------------------------------------------------------------------?
SIGIOT 6 C IO捕獲指令,與SIGABRT同義?
SIGEMT 7,-,7?
SIGSTKFLT -,16,- A 協處理器堆棧錯誤?
SIGIO 23,29,22 A 某I/O操作現在可以進行了(4.2 BSD)?
SIGCLD -,-,18 A 與SIGCHLD同義?
SIGPWR 29,30,19 A 電源故障(System V)?
SIGINFO 29,-,- A 與SIGPWR同義?
SIGLOST -,-,- A 文件鎖丟失?
SIGWINCH 28,28,20 B 窗口大小改變(4.3 BSD, Sun)?
SIGUNUSED -,31,- A 未使用的信號(will be SIGSYS)?

(在這里,- 表示信號沒有實現;有三個值給出的含義為,第一個值通常在Alpha和Sparc上有效,中間的值對應i386和ppc以及sh,最后一個值對應mips。信號29在Alpha上為SIGINFO / SIGPWR ,在Sparc上為SIGLOST。)?

處理動作一項中的字母含義如下?
A 缺省的動作是終止進程?
B 缺省的動作是忽略此信號?
C 缺省的動作是終止進程并進行內核映像轉儲(dump core)?
D 缺省的動作是停止進程?
E 信號不能被捕獲?
F 信號不能被忽略


代碼測試

#include<stdio.h> #include<signal.h> #include<unistd.h> #include<stdlib.h> void when_alarm(); void when_sigint(); void when_sigchld(int); void when_sigusr1(); void when_sigio(); int main() { int childpid;//子程序進程ID號 printf("程序已經開始運行,5秒鐘后將接收到時鐘信號。/n"); if ((childpid=fork())>0)//父進程 { signal(SIGALRM,when_alarm); //當接收到SIGALRM信號時,調用when_alarm函數 signal(SIGINT,when_sigint); //當接收到SIGINT信號時,調用when_sigint函數 signal(SIGCHLD,when_sigchld);//當接收到SIGCHLD信號時,調用when_sigchld函數 signal(SIGUSR1,when_sigusr1);//當接收到SIGUSR1信號時,調用when_sigusr1函數 signal(SIGIO,when_sigio);//當接收到SIGIO信號時,調用when_sigio函數 alarm(5); //5秒鐘之后產生SIGALRM信號 raise(SIGIO); //向自己發送一個SIGIO信號 pause(); //將父進程暫停下來,等待SIGALRM信號到來 pause(); //將父進程暫停下來,等待SIGUSR1信號到來 pause(); //將父進程暫停下來,等待SIGCHLD信號到來 printf("------此時程序會停下來等待,請按下ctrl+c送出SIGINT信號-------/n"); pause(); //將父進程暫停下來,等待SIGINT信號到來 } else if(childpid==0) //子進程 { int timer; for(timer=7;timer>=0;timer--) //時鐘計時5秒產生SIGALRM信號,再過2秒子進程退出,產生SIGCHLD信號 { if(timer>2) printf("距離SIGALRM信號到來還有%d秒。/n",timer-2); if(timer==4) kill(getppid(),SIGUSR1); //向父進程發送一個SIGUSR1信號 if((timer<=2)&&(timer>0)) printf("子進程還剩%d秒退出,屆時會產生SIGCHLD信號。/n",timer); if(timer==0) //子進程退出,產生SIGCHLD信號 raise(SIGKILL); //子進程給自己發一個結束信號 sleep(1); //每個循環延時1秒鐘 } } else printf("fork()函數調用出現錯誤!/n"); return 0; } void when_alarm() { printf("5秒鐘時間已到,系統接收到了SIGALRM信號!/n"); } void when_sigint() { printf("已經接收到了SIGINT信號,程序將退出!/n"); exit(0); } void when_sigchld(int SIGCHLD_num) { printf("收到SIGCHLD信號,表明我的子進程已經中止,SIGCHLD信號的數值是:%d。/n",SIGCHLD_num); } void when_sigusr1() { printf("系統接收到了用戶自定義信號SIGUSR1。/n"); } void when_sigio() { printf("系統接收到了SIGIO信號。/n"); }

總結

以上是生活随笔為你收集整理的linux c之信号signal处理机制的全部內容,希望文章能夠幫你解決所遇到的問題。

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