【轉載】程序的終止 exit函數 abort函數

exit和_exit函數用於正常終止一個程序: _exit立即進入內核,exit則先執行一些清除處理(包括調用執行各終止處理程序,關閉所有標準I / O流等),然後進入內核。使用不同頭文件的原因是:exit是由ANSI C說明的,而_exit則是由POSIX.1說明的。
        由於歷史原因,exit函數總是執行一個標準I/O庫的清除關閉操作:對於所有打開流調用 fclose 函數。exit和_exit都帶一個整型參數,稱之爲終止狀態(exit status)。大多數UNIX shell都提供檢查一個進程終止狀態的方法。如果( a )若調用這些函數時不帶終止狀態,或( b ) main執行了一個無返回值的re turn語句,或( c ) main執行隱式返回,則該進程的終止狀態是末定義的。這就意味着,下列經典性的C語言程序:
              #include <stdio.h>
              main ()
              {
                       printf ("hello, world \n");
              }
        是不完整的,因爲main函數沒有使用return語句返回(隱式返回),它在返回到C的起動例程時並沒有返回一個值(終止狀態)。另外,若使用:
                return( 0 ) ;或者
                exit( 0 );
         則向執行此程序的進程(常常是一個shell進程)返回終止狀態0。另外,main函數的說明實際上應當是:
                                              int main(void)
        將main說明爲返回一個整型以及用exit代替return,對某些C編譯程序和UNIX lint(1)程序而言會產生不必要的警告信息,因爲這些編譯程序並不瞭解main中的exit與return語句的作用相同。警告信息可能是“ control reaches end of nonvoid function(控制到達非void函數的結束處)”。避開這種警告信息的一種方法是:在main中使用return語句而不是exit。但是這樣做的結果是不能用UNIX的grep公用程序來找出程序中所有的exit調用。另外一個解決方法是將main說明爲返回void而不是int,然後仍舊調用exit。這也避開了編譯程序的警告,但從程序設計角度看卻並不正確。本章將main表示爲返回一個整型,因爲這是ANSIC和POSIX.1所定義的。我們將不理會編譯程序不必要的警告。
atexit函數
        按照ANSI C的規定,一個進程可以登記多至32個函數,這些函數將由exit自動調用。我們稱這些函數爲終止處理程序(exit handler),並用atexit函數來登記這些函數。
                                  #include <stdlib.h>
                                  int atexit(void *( func) ( void ) ) ;
                                                                                                          返回:若成功則爲0,若出錯則爲非0
        其中, atexit的參數是一個函數地址,當調用此函數時無需向它傳送任何參數,也不期望它返回一個值。exit以登記這些函數的相反順序調用它們。同一函數如若登記多次,則也被調用多次。
         終止處理程序這一機制由ANSI C最新引進。S V R 4和4 . 3 + B S D都提供這種機制。系統V的早期版本和4 . 3 B S D則都不提供此機制。
        根據ANSI C和POSIX.1,exit首先調用各終止處理程序,然後按需多次調用fclose,關閉所有打開流。圖中顯示了一個C程序是如何起動的,以及它終止的各種方式。注意,內核使程序執行的唯一方法是調用一個e x e c函數。進程自願終止的唯一方法是顯式或隱式地(調用e x i t )調用_ e x i t。進程也可非自願地由一個信號使其終止。

進程有三種正常終止法及兩種異常終止法。
(1) 正常終止:
(a) 在m a i n函數內執行r e t u r n語句。如在7 . 3節中所述,這等效於調用e x i t。
(b) 調用e x i t函數。此函數由ANSI C定義,其操作包括調用各終止處理程序(終止處理程序在調用a t e x i t函數時登錄),然後關閉所有標準I / O流等。因爲ANSI C並不處理文件描述符、多進程(父、子進程)以及作業控制,所以這一定義對U N I X系統而言是不完整的。
(c) 調用_ e x i t系統調用函數。此函數由e x i t調用,它處理U N I X特定的細節。_ e x i t是由P O S I X . 1說明的。
(2) 異常終止:
(a) 調用a b o r t。它產生S I G A B RT信號,所以是下一種異常終止的一種特例。
(b) 當進程接收到某個信號時。(第1 0章將較詳細地說明信號。)進程本身(例如調用a b o r t函數)、其他進程和內核都能產生傳送到某一進程的信號。例如,進程越出其地址空間訪問存儲單元,或者除以0,內核就會爲該進程產生相應的信號。不管進程如何終止,最後都會執行內核中的同一段代碼。這段代碼爲相應進程關閉所有打
開描述符,釋放它所使用的存儲器等等。對上述任意一種終止情形,我們都希望終止進程能夠通知其父進程它是如何終止的。對於e x i t和_ e x i t,這是依靠傳遞給它們的退出狀態( exit status)參數來實現的。在異常終止情況,內核(不是進程本身)產生一個指示其異常終止原因的終止狀態( termination status)。在任意一種情況下,該終止進程的父進程都能用w a i t或w a i t p i d函數(在下一節說明)取得其終止狀態。
注意,這裏使用了“退出狀態”(它是傳向e x i t或_ e x i t的參數,或m a i n的返回值)和“終止
狀態”兩個術語,以表示有所區別。在最後調用_ e x i t時內核將其退出狀態轉換成終止狀態。

/////************************************************************

 

摘要:本文詳細講述了幾個出錯處理的函數abort、exit、atexit、strerror函數的使用方法,並給出來具體的示例程序。

         
函數名: abort
功 能: 異常終止一個進程
用 法: void abort(void);
頭文件:#include <stdlib.h>
說明:abort函數是一個比較嚴重的函數,當調用它時,會導致程序異常終止,
而不會進行一些常規的清除工作,比如釋放內存等。
程序例:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   puts( "About to abort....\n" );
   abort();
  
    puts( "This will never be executed!\n" );
    exit( EXIT_SUCCESS );
}
 

[root@localhost error_process]# gcc abort.c
[root@localhost error_process]# ./a.out
About to abort....

已放棄


表頭文件 #include<stdlib.h>
定義函數 void exit(int status);

exit()用來正常終結目前進程的執行,並把參數 status 返回給父進程,
而進程所有的緩衝區數據會自動寫回並關閉未關閉的文件。
它並不像abort那樣不做任何清理工作就退出,而是在完成所有的清理工作後才退出程序。


atexit(設置程序正常結束前調用的函數)

表頭文件 #include<stdlib.h>
定義函數 int atexit (void (*function)(void));

    atexit()用來設置一個程序正常結束前調用的函數。當程序通過調
    用 exit()或從 main 中返回時,參數 function 所指定的函數會先被
    調用,然後才真正由 exit()結束程序。
   
返回值 如果執行成功則返回 0,否則返回-1,失敗原因存於 errno 中。

#include <stdlib.h>
#include <stdio.h>

void my_exit(void)
{
    printf( "Before exit....\n" );
}

int main(void)
{
    atexit( my_exit );
    return 0;
}
 

[root@localhost error_process]# gcc atexit.c
[root@localhost error_process]# ./a.out
Before exit....



strerror(返回錯誤原因的描述字符串)

表頭文件     #include<string.h>
定義函數     char * strerror(int errnum);
          strerror()   用來依參數 errnum 的錯誤代碼來查詢其錯誤原因的描述字符串,然後將該字符串指針返回。
          這時如果把 errno 傳個strerror,就可以得到可讀的提示信息,而不再是一個冷冰冰的數字了。
         
返回值      返回描述錯誤原因的字符串指針。

#include <string.h>
#include <stdio.h>

int main(void)
{
    int i;
   
    for ( i=0; i<10; i++ )
    {
        printf( "%d:%s\n", i, strerror(i) );
    }   
   
    return 0;
}

[root@localhost error_process]# gcc strerror.c
[root@localhost error_process]# ./a.out
0:Success
1:Operation not permitted
2:No such file or directory
3:No such process
4:Interrupted system call
5:Input/output error
6:No such device or address
7:Argument list too long
8:Exec format error
9:Bad file descriptor
[root@localhost error_process]#
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章