1. 程式人生 > >淺析exit()和atexit()函式【轉】

淺析exit()和atexit()函式【轉】

 

(轉自:https://blog.csdn.net/wy1550365215/article/details/70216750

當核心使用一個一個exec函式執行c程式時,在呼叫main函式之前先呼叫一個特殊的啟動例程,可執行程式需將此例程指定為程式的起始地址。啟動例程從核心獲取命令列引數和環境變數,然後為呼叫mian函式做好準備。 


exec函式說明: 
fork函式是用於建立一個子程序,該子程序幾乎是父程序的副本,而有時我們希望子程序去執行另外的程式,exec函式族就提供了一個在程序中啟動另一個程式執行的方法。它可以根據指定的檔名或目錄名找到可執行檔案,並用它來取代原呼叫程序的資料段、程式碼段和堆疊段,在執行完之後,原呼叫程序的內容除了程序號外,其他全部被新程式的內容替換了。另外,這裡的可執行檔案既可以是二進位制檔案,也可以是Linux下任何可執行指令碼檔案。 


那麼在linux中呼叫exec函式有兩種情況: 
1)當程序認為自己不能再為系統和使用者做出任何貢獻時,就可以呼叫任何exec 函式族讓自己重生。 
2)如果一個程序想執行另一個程式,那麼它就可以呼叫fork函式新建一個程序,然後呼叫任何一個exec函式使子程序重生。

 
程序終止: 


程序種植的方式有8種,前5種為正常終止,後3種為異常終止: 
1 從main函式返回 
2 調⽤用exit函式; 
3 調⽤用_exit或_Exit; 
4 最後⼀一個執行緒從啟動例程返回; 
5 最後⼀一個執行緒調⽤用pthread_exit; 
6 調⽤用abort函式; 
7 接到⼀一個訊號並終⽌止; 
8 最後⼀一個執行緒對取消請求做出響應。 
一般我們都是使用exit函式正常終止程序

 

#include <stdlib.h>
void exit( int status );
void _Exit( int status );
#include <unistd.h>
void _exit( int status );


_exit和_Exit立即進入核心,而exit要先做一些清理工作(呼叫執行個終止處理程式,關閉所有標準I/O流),再進入核心。三個函式所帶的整形引數稱為終止狀態或退出狀態,如果(a)呼叫這些函式不帶引數,(b)main函式中的return 語句無返回值,(c)main函式沒有宣告返回型別為整形,則程序的終止狀態是未定義

的。main函式返回一個整形值與用該值呼叫exit是等價的。 


注意: 
exit函式執行時首先會執行由atexit()函式登記的函式,然後會做一些自身的清理工作,同時重新整理所有輸出流、關閉所有開啟的流並且關閉通過標準I/O函式tmpfile()建立的臨時檔案。 
exit()函式用於在程式執行的過程中隨時結束程式,exit的引數state是返回給作業系統,返回0表示程式正常結束,非0表示程式非正常結束。 


atexit函式: 
atexit函式是一個特殊的函式,它是在正常程式退出時呼叫的函式,我們把他叫為登記函式 
(函式原型:int atexit (void (*)(void)))

 

一個程序可以登記若32個函式,這些函式由exit自動呼叫,這些函式被稱為終止處理函式,atexit函式可以登記這些函式。exit呼叫終止處理函式的順序和atexit登記的順序相反,如果一個函式被多次登記,也會被多次呼叫。


驗證atexit函式: 
 這裡寫圖片描述 
執行結果為: 

這裡寫圖片描述 
 
先列印hello main睡眠五秒再依次列印test5,test4,test3,test2,test1(如果main函式中printf部分不加\n,則main函式要輸出的內容會先放到標準輸出緩衝區中,睡眠5秒後再打印出來,當main中呼叫exit函式的時候,會做一些自身清理工作,同時重新整理標準輸出緩衝區中的內容),當執行到exit(0)時,exit會自動呼叫已註冊過的函式,但是由於壓棧過程中先進後出的原則,所以先註冊的函式最後執行。如果一個函式被atexit()登記多次也會被exit()呼叫多次。

 


--------------------- 
作者:一個位元組 
來源:CSDN 
原文:https://blog.csdn.net/wy1550365215/article/details/70216750 
版權宣告:本文為博主原創文章,轉載請附上博文連結!