Linux內核的信號機制——怪胎

信號機制是Unix的一大特色,因爲是特色,所以很多同學在編程時,有些不能理解(超出理解範圍?)。

本文對Linux信號機制做一個分析。

常見signal使用如下:

void mysig(){

printf("got a sig!\n");

}

int main() { 
printf("process id is %d !\n",getpid()); 
signal(SIGINT, mysig); 
for (;;) ; 

當我們在控制檯按Ctrl + C時,控制檯會打印出"got a sig!"。

這個過程到底發生了什麼?

如果你沒有深入思考過操作系統的工作原理,就算是寫過幾年的C程序,也是一頭霧水。

如果是初學C,都知道,C程序是從main函數開始,跑到最後一行,順序執行!signal的概念完全就是個怪胎!

signal的內核操作過程如下:

1,signal()系統調用,發生0x80中斷(陷阱),調用sys_signal()。

2,sys_signal()獲取到傳入的信號編號(SIGINT等宏定義),以及對應的handler,把它註冊到current宏的sigaction[signum-1],current宏指向了正在執行的task_struct,而sigaction是task_struct的一個成員。

3,中斷服務程序執行完畢之後,準備返回用戶程序,返回之前,檢查當前進程可以處理的信號——此時,信號可能(一般)還沒發生。

4,程序員按了Ctrl +C,內核接收到這個信號了,對應的sigaction的選項被標記。

5,內核又發生了中斷,返回用戶程序前,檢查可以處理的信號,發現有信號可以處理,do_signal(),跳轉到註冊的handler(),程序員感覺到穿越了(也就是最難理解的地方)

6,handler()執行完畢之後,執行特殊系統調用,返回內核態。

7,從內核態返回用戶模式,出棧,恢復到中斷髮生之前,接着執行之前的代碼。


所以,關鍵還是對中斷的理解——理解了中斷,linux內核就理解了三分之一!

發佈了171 篇原創文章 · 獲贊 9 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章