Ctrl-C中斷當(dāng)前運行的程序截酷。這個中斷由一個稱為信號的內(nèi)核機制產(chǎn)生培漏。
什么是信號,它從哪里來
- 用戶
用戶能夠通過Ctrl-C溪厘、Ctrl-Z或是終端驅(qū)動程序分配給信號控制字符的其他按鍵來請求內(nèi)核產(chǎn)生信號。 - 內(nèi)核
當(dāng)進程執(zhí)行出錯時牌柄,內(nèi)核給進程發(fā)送一個信號畸悬,如非法讀取內(nèi)存,浮點數(shù)溢出珊佣。 - 進程
一個進程可以通過系統(tǒng)調(diào)用kill
給另一個進程發(fā)送信號蹋宦。即,進程間可以通過信號機制進行通信咒锻。
由于進程的某個操作所產(chǎn)生的信號叫同步信號
冷冗,如除數(shù)為0;由于用戶鍵盤輸入的進程外信號叫異步信號
惑艇。
信號代碼定義在/usr/include/signal.h
中蒿辙。
進程如何處理信號
當(dāng)進程收到SIGINT
時,并不一定銷毀滨巴。進程通過系統(tǒng)調(diào)用signal
告訴內(nèi)核自己想怎樣處理這個信號思灌。具體有三種選擇
- 默認處理(通常是消亡)
每個信號都有自己的默認處理方式。SIGINT
的默認處理方式是消亡恭取。進程可以通過下列調(diào)用恢復(fù)默認處理signal(SIGINT, SIG_DEL);
- 忽略信號
signal(SIGINT, SIG_IGN);
- 調(diào)用函數(shù)
告訴內(nèi)核收到信號時泰偿,調(diào)用自定義的函數(shù)signal(SIGINT, func);
func
進行處理。這適用于發(fā)生中斷時進行必要的清理工作蜈垮。
簡單的例子
#include <signal.h>
#include <stdio.h>
int main()
{
void f(int); // 信號處理函數(shù)
int i;
signal(SIGINT, f); //注冊處理函數(shù)
for(i=0; i<5; ++i)
{
printf("hello signal!\n");
sleep(1);
}
return 1;
}
void f(int signum)
{
printf("dolly\n");
}
程序由兩部分組成:main函數(shù)和信號處理函數(shù)f耗跛。程序首先照常執(zhí)行main函數(shù)的循環(huán),如果進程收到SIGINT
信號攒发,內(nèi)核函數(shù)會調(diào)用注冊的f函數(shù)调塌,然后返回到跳轉(zhuǎn)前的位置。
考慮一個問題:屏蔽所有信號并在程序中執(zhí)行死循環(huán)惠猿,程序會一直執(zhí)行下去羔砾,無法干涉嗎?
實際上Unix不允許這種情況發(fā)生,因為并不是所有的信號都允許被忽略:SIGKILL
和SIGSTOP
蜒茄。