上一節講過,SIGINT
的預設處理動作是終止進程,SIGQUIT
的預設處理動作是終止進程並且Core Dump,現在我們來驗證一下。
首先解釋什麼是Core Dump。當一個進程要異常終止時,可以選擇把進程的用戶空間內存數據全部保存到磁碟上,檔案名通常是core
,這叫做Core Dump。進程異常終止通常是因為有Bug,比如非法內存訪問導致段錯誤,事後可以用調試器檢查core
檔案以查清錯誤原因,這叫做Post-mortem Debug。一個進程允許產生多大的core
檔案取決於進程的Resource Limit(這個信息保存在PCB中)。預設是不允許產生core
檔案的,因為core
檔案中可能包含用戶密碼等敏感信息,不安全。在開發調試階段可以用ulimit
命令改變這個限制,允許產生core
檔案。
首先用ulimit
命令改變Shell進程的Resource Limit,允許core
檔案最大為1024K:
$ ulimit -c 1024
然後寫一個死循環程序:
#include <unistd.h> int main(void) { while(1); return 0; }
前台運行這個程序,然後在終端鍵入Ctrl-C或Ctrl-\:
$ ./a.out (按Ctrl-C) $ ./a.out (按Ctrl-\)Quit (core dumped) $ ls -l core* -rw------- 1 akaedu akaedu 147456 2008-11-05 23:40 core
ulimit
命令改變了Shell進程的Resource Limit,a.out
進程的PCB由Shell進程複製而來,所以也具有和Shell進程相同的Resource Limit值,這樣就可以產生Core Dump了。
仍以上一節的死循環程序為例,首先在後台執行這個程序,然後用kill
命令給它發SIGSEGV
信號。
$ ./a.out & [1] 7940 $ kill -SIGSEGV 7940 $(再次回車) [1]+ Segmentation fault (core dumped) ./a.out
7940是a.out
進程的id。之所以要再次回車才顯示Segmentation fault
,是因為在7940進程終止掉之前已經回到了Shell提示符等待用戶輸入下一條命令,Shell不希望Segmentation fault
信息和用戶的輸入交錯在一起,所以等用戶輸入命令之後才顯示。指定某種信號的kill
命令可以有多種寫法,上面的命令還可以寫成kill -SEGV 7940
或kill -11 7940
,11是信號SIGSEGV
的編號。以往遇到的段錯誤都是由非法內存訪問產生的,而這個程序本身沒錯,給它發SIGSEGV
也能產生段錯誤。
kill
命令是調用kill
函數實現的。kill
函數可以給一個指定的進程發送指定的信號。raise
函數可以給當前進程發送指定的信號(自己給自己發信號)。
#include <signal.h> int kill(pid_t pid, int signo); int raise(int signo);
這兩個函數都是成功返回0,錯誤返回-1。
abort
函數使當前進程接收到SIGABRT
信號而異常終止。
#include <stdlib.h> void abort(void);
就像exit
函數一樣,abort
函數總是會成功的,所以沒有返回值。
SIGPIPE
是一種由軟件條件產生的信號,在例 30.7 “管道”中已經介紹過了。本節主要介紹alarm
函數和SIGALRM
信號。
#include <unistd.h> unsigned int alarm(unsigned int seconds);
調用alarm
函數可以設定一個閙鐘,也就是告訴內核在seconds
秒之後給當前進程發SIGALRM
信號,該信號的預設處理動作是終止當前進程。這個函數的返回值是0或者是以前設定的閙鐘時間還餘下的秒數。打個比方,某人要小睡一覺,設定閙鐘為30分鐘之後響,20分鐘後被人吵醒了,還想多睡一會兒,於是重新設定閙鐘為15分鐘之後響,“以前設定的閙鐘時間還餘下的時間”就是10分鐘。如果seconds
值為0,表示取消以前設定的閙鐘,函數的返回值仍然是以前設定的閙鐘時間還餘下的秒數。
例 33.1. alarm
#include <unistd.h> #include <stdio.h> int main(void) { int counter; alarm(1); for(counter=0; 1; counter++) printf("counter=%d ", counter); return 0; }
這個程序的作用是1秒鐘之內不停地數數,1秒鐘到了就被SIGALRM
信號終止。