關於Linux系統命令中exit與exit的區別
注:exit()就是退出,傳入的參數是程序退出時的狀態碼,0表示正常退出,其他表示非正常退出,一般都用-1或者1,標準C裏有EXIT_SUCCESS和EXIT_FAILURE兩個宏,用exit(EXIT_SUCCESS);可讀性比較好一點。
作爲系統調用而言,_exit和exit是一對孿生兄弟,它們究竟相似到什麼程度,我們可以從Linux的源碼中找到答案:
#define__NR__exit__NR_exit/*摘自文件include/asm-i386/unistd.h第334行*/
"__NR_"是在Linux的源碼中爲每個系統調用加上的前綴,請注意第一個exit前有2條下劃線,第二個exit前只有1條下劃線。 這時隨便一個懂得C語言並且頭腦清醒的人都會說,_exit和exit沒有任何區別,但我們還要講一下這兩者之間的區別,這種區別主要體現在它們在函數庫中的定義。_exit在Linux函數庫中的原型是:
#include
和exit比較一下,exit()函數定義在stdlib.h中,而_exit()定義在unistd.h中,從名字上看,stdlib.h似乎比unistd.h高級一點,那麼,它們之間到底有什麼區別呢? _exit()函數的作用最爲簡單:直接使進程停止運行,清除其使用的內存空間,並銷燬其在內核中的各種數據結構;exit()函數則在這些基礎上作了一些包裝,在執行退出之前加了若干道工序,也是因爲這個原因,有些人認爲exit已經不能算是純粹的系統調用。 exit()函數與_exit()函數最大的區別就在於exit()函數在調用exit系統調用之前要檢查文件的打開情況,把文件緩衝區中的內容寫回文件,就是"清理I/O緩衝"。
exit()在結束調用它的進程之前,要進行如下步驟:
1.調用atexit()註冊的函數(出口函數);按ATEXIT註冊時相反的順序調用所有由它註冊的函數,這使得我們可以指定在程序終止時執行自己的清理動作.例如,保存程序狀態信息於某個文件,解開對共享數據庫上的鎖等.
nup();關閉所有打開的流,這將導致寫所有被緩衝的輸出,刪除用TMPFILE函數建立的所有臨時文件.
3.最後調用_exit()函數終止進程。
_exit做3件事(man): 1,Anyopenfiledescriptorsbelongingtotheprocessareclosed 2,anychildrenoftheprocessareinheritedbyprocess1,init 3,theprocess‘sparentissentaSIGCHLDsignal
exit執行完清理工作後就調用_exit來終止進程。
此外,另外一種解釋:
簡單的說,exit函數將終止調用進程。在退出程序之前,所有文件關閉,緩衝輸出內容將刷新定義,並調用所有已刷新的“出口函數”(由atexit定義)。
_exit:該函數是由Posix定義的,不會運行exithandler和signalhandler,在UNIX系統中不會flush標準I/O流。
簡單的說,_exit終止調用進程,但不關閉文件,不清除輸出緩存,也不調用出口函數。
共同:
不管進程是如何終止的,內核都會關閉進程打開的所有filedescriptors,釋放進程使用的memory!
更詳細的介紹:
Callingexit() Theexit()functioncausesnormalprogramtermination.
Theexit()functionperformsthefollowingfunctions:
unctionsregisteredbytheStandardCatexit()functionarecalledinthereverse yofthesefunctionscallsexit(),theresultsarenotportable. penoutputstreamsareflushed(datawrittenout)andthestreamsareclosed.
ilescreatedbytmpfile()ared.
_exit()functioniscalled. Calling_exit() The_exit()functionperformsoperatingsystem-specificprogramterminationfunctions. Theseinclude: penfiledescriptorsanddirectorystreamsareclosed.
eparentprocessisexecutingawait()orwaitpid(),theparentwakesupand statusismadeavailable.
eparentisnotexecutingawait()orwaitpid(),thestatusissavedforreturnto theparentonasubsequentwait()orwaitpid(). :the terminationofaparentdoesnotdirectlyterminateitschildren. eimplementationsupportstheSIGCHLDsignal,aSIGCHLDissenttotheparent. raljobcontrolsignalsaresent.
爲何在一個fork的子進程分支中使用_exit函數而不使用exit函數? ‘exit()’與‘_exit()’有不少區別在使用‘fork()’,特別是‘vfork()’時變得很 突出。
‘exit()’與‘_exit()’的基本區別在於前一個調用實施與調用庫裏用戶狀態結構(user-modeconstructs)有關的清除工作(clean-up),而且調用用戶自定義的清除程序(自定義清除程序由atexit函數定義,可定義多次,並以倒序執行),相對應,_exit函數只爲進程實施內核清除工作。 在由‘fork()’創建的`子進程分支裏,正常情況下使用‘exit()’是不正確的,這是因爲使用它會導致標準輸入輸出(stdio:StandardInputOutput)的緩衝區被清空兩次,而且臨時文件被出乎意料的刪除(臨時文件由tmpfile函數創建在系統臨時目錄下,文件名由系統隨機生成)。在C++程序中情況會更糟,因爲靜態目標(staticobjects)的析構函數(destructors)可以被錯誤地執行。(還有一些特殊情況,比如守護程序,它們的父進程需要調用‘_exit()’而不是子進程;適用於絕大多數情況的基本規則是,‘exit()’在每一次進入‘main’函數後只調用一次。) 在由‘vfork()’創建的子進程分支裏,‘exit()’的使用將更加危險,因爲它將影響父進程的狀態。
#include
子進程關閉的是自己的,雖然他們共享標準輸入、標準輸出、標準出錯等“打開的文件”,子進程exit時,也不過是遞減一個引用計數,不可能關閉父進程的,所以父進程還是有輸出的。
但在其它UNIX系統上,父進程可能沒有輸出,原因是子進程調用了exit,它刷新關閉了所有標準I/O流,這包括標準輸出。雖然這是由子進程執行的,但卻是在父進程的地址空間中進行的,所以所有受到影響的標準I/OFILE對象都是在父進程中的。當父進程調用printf時,標準輸出已被關閉了,於是printf返回-1。
在Linux的標準函數庫中,有一套稱作"高級I/O"的函數,我們熟知的printf()、fopen()、fread()、fwrite()都在此列,它們也被稱作"緩衝I/O(bufferedI/O)",其特徵是對應每一個打開的文件,在內存中都有一片緩衝區,每次讀文件時,會多讀出若干條記錄,這樣下次讀文件時就可以直接從內存的緩衝區中讀取,每次寫文件的時候,也僅僅是寫入內存中的緩衝區,等滿足了一定的條件(達到一定數量,或遇到特定字符,如換行符和文件結束符EOF),再將緩衝區中的內容一次性寫入文件,這樣就大大增加了文件讀寫的速度,但也爲我們編程帶來了一點點麻煩。如果有一些數據,我們認爲已經寫入了文件,實際上因爲沒有滿足特定的條件,它們還只是保存在緩衝區內,這時我們用_exit()函數直接將進程關閉,緩衝區中的數據就會丟失,反之,如果想保證數據的完整性,就一定要使用exit()函數。
Exit的函數聲明在stdlib.h頭文件中。
_exit的函數聲明在unistd.h頭文件當中。
下面的實例比較了這兩個函數的區別。printf函數就是使用緩衝I/O的方式,該函數在遇到“n”換行符時自動的從緩衝區中將記錄讀出。實例就是利用這個性質進行比較的。
exit.c源碼
#include
輸出信息:
Usingexit...
Thisisthecontentinbuffer
#include
則只輸出:
Usingexit...
說明:在一個進程調用了exit之後,該進程並不會馬上完全消失,而是留下一個稱爲殭屍進程(Zombie)的數據結構。殭屍進程是一種非常特殊的進程,它幾乎已經放棄了所有的內存空間,沒有任何可執行代碼,也不能被調度,僅僅在進程列表中保留一個位置,記載該進程的退出狀態等信息供其它進程收集,除此之外,殭屍進程不再佔有任何內存空間。
#include
intmain() { printf("%c",‘c‘); _exit(0); }
相關文章
-
Linux_ext2/ext3文件系統介紹
Linux ext2/ext3文件系統使用索引節點來記錄文件信息,作用像windows的文件分配表。索引節點是一個結構,它包含了一個文件的長度、創建及修改時間、權限、所屬關係、磁盤中的位置等信息。一個文件系統維護了一個索引節點 -
Linux系統中smbclient命令的使用方法
Linux命令smbclient主要是用來存儲和讀取服務器上的用戶端程序,並對這些程序進行解析和記錄。本文就來具體介紹一下Linux系統smbclient命令的使用方法。1、列出某個IP地址所提供的.共享文件夾smbclient -L -U useame% -
使用w命令和uptime命令來查看Linux系統的負載
在前面的教程中我們有提到,使用top、vmstat等命令可以查看Linux系統CPU的使用率,即系統負載。 除了這些命令外,還可使用w命令和uptime命令來查看Linux系統的負載,一起來了解下吧。1. w命令[root@linuxidc ~]# w14:44:27 up -
Linux系統是怎麼辨別gmtime和localtime
gmtime和localtime是兩種不同的函數,不少人在使用的時候容易將兩者混淆,下面小編就教你Linux下如何辨別gmtime和localtime的使用,以便你下次能夠正確使用。區別:#include 《time.h》#include 《stdio.h》int main(int argc -
Linux系統中hexdump的命令彙總
hexdump是Linux系統中用來查看文件十六進制編碼的命令,配合不同的參數其作用也有所不同,下面小編就給大家介紹下Linux中hexdump命令的用法,不瞭解的`朋友不妨來學習一下。查看一些二進制文件的內容,比如二進制文件中包含 -
Linux認證系統管理:linuxmail命令發送郵件失敗
使用linux自帶的'郵件功能測試郵件發送功能如下:$ mail -s test sldkfjlskdjf[CTRL+D]cc:有時會出再提示:You have a new mail in /var/spool/mail/root並且在郵箱中看不到郵件;解決辦法:1.查看出錯的日誌$ tail -n 5 -
託福英語寫作範文:Examinations exert a pernicious influence on educat
We might marvel at the progress made in every field of study, but the methods of testing a person’s knowledge and ability remain as primitive as ever they were. It really is extraordinary that after -
Linux系統xlsatom命令如何使用
在Linux系統中有很多命令,理論上可以用Linux命令完成所有鼠標鍵盤的操作。xlsatoms命令可以用來定義搜索文件的範圍和成分,下面小編就給大家介紹一下Linux系統xlsatoms命令的.使用說明。一起去看看吧!功能說明:列出X Ser -
Linux系統中strace命令的使用代碼
目前國有企業資產轉讓中存在一些問題,如轉讓資產的範圍具有隨意性,轉讓的決定權不明確,轉讓前資產評估不嚴格,轉讓資產所得收益用途不適當,轉讓方式缺乏公開性與競爭性,那麼簽訂企業資產轉讓協議書需要注意什麼呢?以下 -
Linux關閉selinux安全子系統的技巧
selinux是Linux的安全子系統,是一個強制訪問控制安全模塊,那麼要如何關閉selinux安全子系統呢?下面小編就給大家介紹下Linux關閉selinux安全子系統的技巧,一起來學習下吧。1、首先我們可以用命令來查看selinux的狀態geten