天天看點

程序的幾種退出機制

Linux 下程序的退出分為正常退出和異常退出兩種:

1.正常退出

a. 在main()函數中執行return 。

b.調用exit()函數

c.調用_exit()函數

2.異常退出

a.調用abort函數

b.程序收到某個信号,而該信号使程式終止。

但不管是哪種退出方式,系統最終都會執行核心中的某一代碼。這段代碼用來關閉程序所用已打開的檔案描述符,釋放它所占用的記憶體和其他資源。

幾種退出方式的比較

1.exit和return 的差別:

exit是一個函數,有參數。exit執行完後把控制權交給系統

return是函數執行完後的傳回。renturn執行完後把控制權交給調用函數。

2.exit和abort的差別:

exit是正常終止程序

abort是異常終止。

3. exit()和_exit()函數的差別

exit和_exit函數都是用來終止程序的。當程式執行到exit或_exit時,系統無條件的停止剩下所有操作,清除各種資料結構,并終止本程序的運作。

a. exit在頭檔案stdlib.h中聲明,而_exit()聲明在頭檔案unistd.h中聲明。 exit中的參數exit_code為0代表程序正常終止,若為其他值表示程式執行過程中有錯誤發生。

b. _exit()執行後立即傳回給核心,而exit()要先執行一些清除操作,然後将控制權交給核心。

c. 調用_exit函數時,其會關閉程序所有的檔案描述符,清理記憶體以及其他一些核心清理函數,但不會重新整理流(stdin, stdout, stderr ...). exit函數是在_exit函數之上的一個封裝,其會調用_exit,并在調用之前先重新整理流。

d. exit()函數與_exit()函數最大差別就在于exit()函數在調用exit系統之前要檢查檔案的打開情況,把檔案緩沖區的内容寫回檔案。由于Linux的标準函數庫中,有一種被稱作“緩沖I/O”的操作,其特征就是對應每一個打開的檔案,在記憶體中都有一片緩沖區。每次讀檔案時,會連續的讀出若幹條記錄,這樣在下次讀檔案時就可以直接從記憶體的緩沖區讀取;同樣,每次寫檔案的時候也僅僅是寫入記憶體的緩沖區,等滿足了一定的條件(如達到了一定數量或遇到特定字元等),再将緩沖區中的内容一次性寫入檔案。這種技術大大增加了檔案讀寫的速度,但也給程式設計代來了一點兒麻煩。比如有一些資料,認為已經寫入了檔案,實際上因為沒有滿足特定的條件,它們還隻是儲存在緩沖區内,這時用_exit()函數直接将程序關閉,緩沖區的資料就會丢失。是以,要想保證資料的完整性,就一定要使用exit()函數。

通過一個函數執行個體來看看它們之間的差別:

函數執行個體1 : exit.c

#include <stdio.h >

#include <stdlib.h>

int main()

{

printf("using exit----\n");

printf("This is the content in buffer\n");

exit(0);

}

執行結果為:

using exit----

This is the content in buffer

函數執行個體2:_exit.c

#include <stdio.h >

#include <unistd.h>

int main()

{

printf("using _exit--\n");

printf("This is the content in buffer");

_exit(0);

}

執行結果為 :

using _exit--

printf函數就是使用緩沖I/O的方式,該函數在遇到“\n”換行符時自動的從緩沖區中将記錄讀出。是以exit()将緩沖區的資料寫完後才退出,而_exit()函數直接退出。

大家也可以把函數執行個體2中的printf("This is the content in buffer");改為printf("This is the content in buffer\n")(即在printf中最後加一個\n看運作結果是什麼,為什麼會産生這樣的結果呢?)

父子程序終止的先後順序不同會産生不同的結果

1.父程序先于子程序終止:

此種情況就是我們前面所用的孤兒程序。當父程序先退出時,系統會讓init程序接管子程序 。

2.子程序先于父程序終止,而父程序又沒有調用wait函數

此種情況子程序進入僵死狀态,并且會一直保持下去直到系統重新開機。子程序處于僵死狀态時,核心隻儲存程序的一些必要資訊以備父程序所需。此時子程序始終占有着資源,同時也減少了系統可以建立的最大程序數。

什麼是 僵死狀态呢?