有8種方式使進程終止(termination),其中5種為正常終止,它們是:
(1)從main返回。
(2)調用exit。
(3)調用_exit或_Exit。
(4)最后一個線程從其啟動例程返回。
(5)最后一個線程調用pthread_exit。
異常終止有3種方式,它們是:
(6)調用abort。
(7)接到一個信號并終止。
(8)最后一個線程對取消請求作出響應。
啟動例程是這樣編寫的,使得從main返回后立即調用exit函數。(關于啟動例程:http://learn.akae.cn/media/ch19s02.html)。如果將啟動例程以C代碼形式表示(實際上該例程常常用匯編語言編寫),則它調用main函數的形式可能是:
exit( main( argc, argv ) );
1、exit函數
有三個函數用于正常終止一個程序:_exit和_Exit立即進入內核,exit則先執行一些清理處理(包括調用執行各終止處理程序,關閉所有標準I/O流等),然后進入內核。
#include <stdlib.h>void exit( int status );void _Exit( int status );#include <unistd.h>void _exit( int status );
exit函數總是執行一個標準I/O庫的清理關閉操作:為所有打開流調用fclose函數。這會造成所有緩沖的輸出數據都被沖洗(寫到文件上)。
三個exit函數都帶一個整型參數,稱為終止狀態(或退出狀態,exit status)。大多數UNIX shell都提供檢查進程終止狀態的方法。如果(a)若調用這些函數時不帶終止狀態,或(b)main執行了一個無返回值的return語句,或(c)main沒有聲明返回類型為整型,則該進程的終止狀態是未定義的。但是,若main的返回類型是整型,并且main執行到最后一條語句時返回(隱式返回),那么該進程的終止狀態是0。
main函數返回一整型值與用該值調用exit是等價的。于是在main函數中
exit(0); 等價于 return(0);
2、atexit函數
按照ISO C規定,一個進程可以登記多達32個函數,這些函數將由exit自動調用。我們稱這些函數為終止處理程序(exit handler),并調用atexit函數來登記這些函數。
#include <stdlib.h>int atexit( void (*func)(void) );返回值:若成功則返回0,若出錯則返回非0值
其中,atexit的參數是一個函數地址,當調用此函數時無需向它傳遞任何參數,也不期望它返回一個值。exit調用這些函數的順序與它們登記時候的順序相反。同一函數若登記多次,則也會被調用多次。
根據ISO C和POSIX.1,exit首先調用各終止處理程序,然后按需要多次調用fclose,關閉所有打開流。POSIX.1擴展了ISO C標準,它指定如若程序調用exec函數族中的任一函數,則將清除所有已安裝的終止處理程序。圖7-1顯示了一個C程序是如何啟動的,以及它可以終止的各種方式。
從上圖我們可以總結出exit和_exit的區別如下圖(詳情請參考http://www.CUOXin.com/mickole/p/3186606.html):
注意,內核使程序執行的唯一方法是調用一個exec函數。進程自愿終止的唯一方法是顯式或隱式地(通過調用exit)調用_exit或_Exit。進程也可非自愿地由一個信號使其終止。
程序清單7-2 終止處理程序實例
[root@localhost apue]# cat PRog7-2.c#include "apue.h"static void my_exit1(void);static void my_exit2(void);intmain(void){ if(atexit(my_exit2) != 0) err_sys("can't register my_exit2"); if(atexit(my_exit1) != 0) err_sys("can't register my_exit1"); if(atexit(my_exit1) != 0) err_sys("can't register my_exit1"); printf("main is done/n"); return(0);}static voidmy_exit1(void){ printf("first exit handler/n");}static voidmy_exit2(void){ printf("second exit handler/n");}
執行該程序產生:
[root@localhost apue]# ./prog7-2main is donefirst exit handlerfirst exit handlersecond exit handler
終止處理程序每登記一次,就會被調用一次。在程序清單7-2中,第一個終止處理程序被登記兩次,所以也會被調用兩次。
本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。
新聞熱點
疑難解答