linux exit 和 _exit的區別


今天仔細看了一下exit和_exit這兩個函數的區別,實際上exit也是調用了_exit退出函數的,只不過在調用_exit之前,exit還進行了一些多余的工作,也正是因為這樣,相比起來exit就沒有那么接近底層的系統調用,更應該說是包裝過的標准C庫函數。_exit包含在頭文件unistd.h中,exit包含在頭文件stdlib.h中,我們來查看一下他們的函數原型。

man _exit :

很顯然,_exit函數做這三件事情:

1. 讓調用的進程馬上終止。

2.關閉所有由這個進程打開的文件描述符。

3.調用進程的所有子進程都被初始化init進程收養,調用進程將發送SIGCHLD給他的父進程(這都是因為他即將要退出了,當然要安頓好自己的孩子和告別父母啦)。

 

man exit:

exit則做了這幾件事:

1.按axexit或者on_exit注冊時相反的順序調用所有由它注冊的函數(出口函數),可以把on_exit看作atexit的擴展。(這使得我們可以指定在程序終止時執行自己的清理動作.例如,保存程序狀態信息於某個文件,解開對共享數據庫上的鎖等。)如果有任意一個注冊的函數不返回(比如這個函數call _exit或者用像SIGKILL這樣的信號把自己干掉了),那么剩余的注冊函數都不會得到執行,而且接下來更深層次的exit都不會被執行。如果一個函數被注冊了多遍,那么也會按順序執行多遍(這些是atexit的特性)

2.所有打開的輸入輸出流都將被清空和關閉,換句話說就是把緩沖區的內容寫回文件中。那些用tmpfile函數創建的臨時文件都將被移除。

3.調用_exit。

 

所以,總的來說,exit就是對_exit進行了一些包裝,使得整個退出的過程顯得不那么粗暴,他們倆的共同點就是都會關閉文件描述符,都會清空內存,但是exit還會額外地清空輸入輸出流緩存,移除臨時創建的文件,調用注冊好的出口函數等等。

現在我們只需要用一個小例子來觀察他們倆的區別就可以了:

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

int main(int argc, char const *argv[])
{
    printf("hello\n");
    printf("  hi");
    exit(0);
    //_exit(0);
    return 0;
}

對於上面這段代碼,我們的執行結果為:

 

而我們把代碼改一改:

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

int main(int argc, char const *argv[])
{
    printf("hello\n");
    printf("  hi");
    //exit(0);
    _exit(0);
    return 0;
}

結果就變成了:

這顯然是因為_exit並沒有進行緩沖區的清空等操作,而exit則會把緩沖的內容都清空。

 

參考博客:

http://blog.chinaunix.net/uid-12461657-id-3140887.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM