Linux中exit與_exit的區別

在exit,_exit的區別

?

-?exit()與_exit()函數的區別(Linux系統中)2012-03-20?15:19:53

分類:?LINUX

注:exit()就是退出,傳入的參數是程序退出時的狀態碼,0表示正常退出,其他表示非正常退出,一般都用-1或者1,標準C里有EXIT_SUCCESSEXIT_FAILURE兩個宏,用exit(EXIT_SUCCESS);可讀性比較好一點。

作為系統調用而言,_exitexit是一對孿生兄弟,它們究竟相似到什么程度,我們可以從Linux的源碼中找到答案:

#define?__NR__exit?__NR_exit?/*?摘自文件include/asm-i386/unistd.h第334行?*/

"__NR_"是在Linux的源碼中為每個系統調用加上的前綴,請注意第一個exit前有2條下劃線,第二個exit前只有1條下劃線。 這時隨便一個懂得C語言并且頭腦清醒的人都會說,_exit和exit沒有任何區別,但我們還要講一下這兩者之間的區別,這種區別主要體現在它們在函數庫中的定義。_exit在Linux函數庫中的原型是:

#i?nclude<unistd.h> void?_exit(int?status);

和exit比較一下,exit()函數定義在stdlib.h中,而_exit()定義在unistd.h中,從名字上看,stdlib.h似乎比?unistd.h高級一點,那么,它們之間到底有什么區別呢? _exit()函數的作用最為簡單:直接使進程停止運行,清除其使用的內存空間,并銷毀其在內核中的各種數據結構;exit()?函數則在這些基礎上作了一些包裝,在執行退出之前加了若干道工序,也是因為這個原因,有些人認為exit已經不能算是純粹的系統調用。 exit()函數與_exit()函數最大的區別就在于exit()函數在調用exit系統調用之前要檢查文件的打開情況,把文件緩沖區中的內容寫回文件,就是"清理I/O緩沖"。?

exit()在結束調用它的進程之前,要進行如下步驟: 1.調用atexit()注冊的函數(出口函數);按ATEXIT注冊時相反的順序調用所有由它注冊的函數,這使得我們可以指定在程序終止時執行自己的清理動作.例如,保存程序狀態信息于某個文件,解開對共享數據庫上的鎖等.

2.cleanup()關閉所有打開的流,這將導致寫所有被緩沖的輸出,刪除用TMPFILE函數建立的所有臨時文件.

3.最后調用_exit()函數終止進程。

_exit3件事(man): 1Any?open?file?descriptors?belonging?to?the?process?are?closed 2any?children?of?the?process?are?inherited?by?process?1,?init 3the?process's?parent?is?sent?a?SIGCHLD?signal

exit執行完清理工作后就調用_exit來終止進程。

此外,另外一種解釋:

簡單的說,exit函數將終止調用進程。在退出程序之前,所有文件關閉,緩沖輸出內容將刷新定義,并調用所有已刷新的“出口函數”(由atexit定義)。

_exit:該函數是由Posix定義的,不會運行exit?handler和signal?handler,在UNIX系統中不會flush標準I/O流。

簡單的說,_exit終止調用進程,但不關閉文件,不清除輸出緩存,也不調用出口函數。

共同:

不管進程是如何終止的,內核都會關閉進程打開的所有file?descriptors,釋放進程使用的memory!

更詳細的介紹:

Calling?exit() The?exit()?function?causes?normal?program?termination.

The?exit()?function?performs?the?following?functions: 1.?All?functions?registered?by?the?Standard?C?atexit()?function?are?called?in?the?reverse order?of?registration.?If?any?of?these?functions?calls?exit(),?the?results?are?not?portable. 2.?All?open?output?streams?are?flushed?(data?written?out)?and?the?streams?are?closed. 3.?All?files?created?by?tmpfile()?are?deleted. 4.?The?_exit()?function?is?called. Calling?_exit() The?_exit()?function?performs?operating?system-specific?program?termination?functions. These?include: 1.?All?open?file?descriptors?and?directory?streams?are?closed. 2.?If?the?parent?process?is?executing?a?wait()?or?waitpid(),?the?parent?wakes?up?and status?is?made?available. 3.?If?the?parent?is?not?executing?a?wait()?or?waitpid(),?the?status?is?saved?for?return?to the?parent?on?a?subsequent?wait()?or?waitpid(). 4.?Children?of?the?terminated?process?are?assigned?a?new?parent?process?ID.?Note:?the termination?of?a?parent?does?not?directly?terminate?its?children. 5.?If?the?implementation?supports?the?SIGCHLD?signal,?a?SIGCHLD?is?sent?to?the?parent. 6.?Several?job?control?signals?are?sent.

為何在一個fork的子進程分支中使用_exit函數而不使用exit函數? ‘exit()’‘_exit()’有不少區別在使用‘fork()’,特別是‘vfork()’時變得很 突出。

‘exit()’‘_exit()’的基本區別在于前一個調用實施與調用庫里用戶狀態結構(user-mode?constructs)有關的清除工作(clean-up),而且調用用戶自定義的清除程序?(自定義清除程序由atexit函數定義,可定義多次,并以倒序執行),相對應,_exit函數只為進程實施內核清除工作。 在由‘fork()’創建的子進程分支里,正常情況下使用‘exit()’是不正確的,這是?因為使用它會導致標準輸入輸出(stdio:?Standard?Input?Output)緩沖區被清空兩次,而且臨時文件被出乎意料的刪除(臨時文件由tmpfile函數創建在系統臨時目錄下,文件名由系統隨機生成)。在C++程序中情況會更糟,因為靜態目標(static?objects)的析構函數(destructors)可以被錯誤地執行。(還有一些特殊情況,比如守護程序,它們的父進程需要調用‘_exit()’而不是子進程;適用于絕大多數情況的基本規則是,‘exit()’在每一次進入main’函數后只調用一次。) 在由‘vfork()’創建的子進程分支里,‘exit()’的使用將更加危險,因為它將影響父進程的狀態。

#include?<sys/types.h>; #include?<stdio.h> int?glob?=?6;?/*?external?variable?in?initialized?data?*/ int main(void) { int?var;?/*?automatic?variable?on?the?stack?*/ pid_t?pid; var?=?88; printf("before?vfork\n";?/*?we?don't?flush?stdio?*/ if?(?(pid?=?vfork())?<?0) printf("vfork?error\n"; else?if?(pid?==?0)?{?/*?child?*/ glob++;?/*?modify?parent's?variables?*/ var++; exit(0);?/*?child?terminates?*/?//子進程中最好還是用_exit(0)比較安全。 } /*?parent?*/ printf("pid?=?%d,?glob?=?%d,?var?=?%d\n",?getpid(),?glob,?var); exit(0); } 在Linux系統上運行,父進程printf的內容輸出:pid?=?29650,?glob?=?7,?var?=?89

子進程?關閉的是自己的,?雖然他們共享標準輸入、標準輸出、標準出錯等?打開的文件,?子進程exit時,也不過是遞減一個引用計數,不可能關閉父進程的,所以父進程還是有輸出的。

但在其它UNIX系統上,父進程可能沒有輸出,原?因是子進程調用了e?x?i?t,它刷新關閉了所有標準I?/?O流,這包括標準輸出。雖然這是由子進程執行的,但卻是在父進程的地址空間中進行的,所以所有受到影響的標準I/O?FILE對象都是在父進程中的。當父進程調用p?r?i?n?t?f時,標準輸出已被關閉了,于是p?r?i?n?t?f返回-?1

Linux的標準函數庫中,有一套稱作"高級I/O"的函數,我們熟知的printf()fopen()fread()fwrite()都在此?列,它們也被稱作"緩沖I/Obuffered?I/O"其特征是對應每一個打開的文件,在內存中都有一片緩沖區,每次讀文件時,會多讀出若干條記錄,這樣下次讀文件時就可以直接從內存的緩沖區中讀取,每次寫文件的時候,也僅僅是寫入內存中的緩沖區,等滿足了一定的條件(達到一定數量,或遇到特定字符,如換行符和文件結束符EOF),?再將緩沖區中的?內容一次性寫入文件,這樣就大大增加了文件讀寫的速度,但也為我們編程帶來了一點點麻煩。如果有一些數據,我們認為已經寫入了文件,實際上因為沒有滿足特?定的條件,它們還只是保存在緩沖區內,這時我們用_exit()函數直接將進程關閉,緩沖區中的數據就會丟失,反之,如果想保證數據的完整性,就一定要使用exit()函數。

Exit的函數聲明在stdlib.h頭文件中。

_exit的函數聲明在unistd.h頭文件當中。

下面的實例比較了這兩個函數的區別。printf函數就是使用緩沖I/O的方式,該函數在遇到“\n”換行符時自動的從緩沖區中將記錄讀出。實例就是利用這個性質進行比較的。

exit.c源碼

#include?<stdlib.h> #include?<stdio.h> int?main(void) { printf("Using?exit...\n"); printf("This?is?the?content?in?buffer"); exit(0); }

輸出信息:

Using?exit...

This?is?the?content?in?buffer

#include?<unistd.h> #include?<stdio.h> int?main(void) { printf("Using?exit...\n");?//如果此處不加“\n”的話,這條信息有可能也不會顯示在終端上。 printf("This?is?the?content?in?buffer"); _exit(0); }

則只輸出:

Using?exit...

說明:在一個進程調用了exit之后,該進程并不會馬上完全消失,而是留下一個稱為僵尸進程(Zombie)的數據結構。僵尸進程是一種非常特殊的進程,它幾乎已經放棄了所有的內存空間,沒有任何可執行代碼,也不能被調度,僅僅在進程列表中保留一個位置,記載該進程的退出狀態等信息供其它進程收集,除此之外,僵尸進程不再占有任何內存空間。

#include?<stdio.h>;

int?main() { printf("%c",?'c'); _exit(0); }

?

?

轉載于:https://www.cnblogs.com/coffewei/p/4053475.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376556.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376556.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376556.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

光標閃爍問題的解決辦法

在調用Windows API函數SetCursor設置光標時&#xff0c;可能會碰到閃爍的問題&#xff1a;移動鼠標&#xff0c;光標在Class Cursor(即注冊窗口類時指定的Cursor)與預設Cursor之間閃爍。 在MSDN上有關SetCursor函數的備注中強調&#xff0c;如果Class Cursor非空&#xff0c;那…

視頻編解碼基礎

文章目錄前戲編解碼技術流程主流視頻編碼標準視頻傳輸面臨的問題視頻傳輸差錯控制視頻傳輸Qos質量保證參數人類視覺系統HVS 以及相應編碼措施正餐編碼層次與碼流結構PB幀編碼IBBP序列編碼結構圖像編碼結構條帶編碼結構宏塊編碼結構塊編碼結構預測技術碼率控制實例H264前戲 編解…

XShell 屏幕鎖定的恢復方法(Ctrl+Q)

操作XShell過程中很多時間大家會習慣性的按CtrlS進行保存. CtrlS在XShell的作用是屏幕鎖定&#xff0c;很多朋友會無法操作&#xff0c;會直接把窗口關閉。 解決方法: 快捷鍵 CtrlQ 即能完成解鎖!轉載于:https://www.cnblogs.com/liangle/p/3173475.html

adb端口被占用

程序不能執行&#xff0c;kill掉任務管理器里面adb服務&#xff0c;重新連接設備仍然有錯 查到可能是adb端口被占用 查看adb用的是哪個端口&#xff1a;C:\Users\wanglin>adb nodaemon server 查看誰占用了這個端口&#xff1a;C:\Users\wanglin>netstat -ano | findstr …

實時語音通訊丟包補償技術

文章目錄基于發送端丟包補償技術原理與媒體無關的前向差錯糾正媒體相關前向差錯糾正交織技術基于接受端丟包補償技術基于插入方法基于插值方法基于重構的方法應用建議非交互式交互式拓展閱讀參考丟包補償技術可以分為兩類&#xff1a;基于發送端補償、基于接受端補償 基于發送…

取得裝置可以顯示頁面的寬度

利用html中的div元素取得<div id"divGetWidth" width100%></div>Jquery:var width$(#divGetWidth).width(); //獲取元素寬度 Javascript:var objdocument.getElementById(divGetWidth);var width obj.offsetWidth轉載于:https://www.cnblogs.…

Xcode添加靜態庫以及編譯選項配置常見問題

本文轉載至 http://www.cnblogs.com/Quains/archive/2013/08/22/3276425.html 一,Xcode編譯出現Link錯誤,出現"duplicate symbols for architecture i386 clang"提示.問題:鏈接時,項目有重名文件.解決:根據錯誤提示,做如下檢查:1.Taraget->Build Settings->Li…

關于并發概念的一些筆記

目錄1、基于鎖的并發數據結構1、并發計數器2、懶惰計數器3、并發鏈表4、并發隊列5、并發散列表總結2、條件變量使用&#xff08;POSIX&#xff09;生產者/消費者 &#xff08;有界緩沖區問題&#xff09;覆蓋條件擴展3、信號量使用二值信號量&#xff08;鎖&#xff09;0值信號…

MYSQL常見出錯代碼 mysql error number

1016錯誤&#xff1a;文件無法打開&#xff0c;使用后臺修復或者使用phpmyadmin進行修復。1044錯誤&#xff1a;數據庫用戶權限不足&#xff0c;請聯系空間商解決1045錯誤&#xff1a;數據庫服務器/數據庫用戶名/數據庫名/數據庫密碼錯誤&#xff0c;請聯系空間商檢查帳戶。105…

建立apk定時自動打包系統第三篇——代碼自動更新、APP自動打包系統

我們的思路是每天下班后團隊各成員在指定的時間&#xff08;例如下午18:30&#xff09;之前把各自的代碼上傳到SVN&#xff0c;然后服務器在指定的時間&#xff08;例如下午18:30&#xff09;更新代碼、執行ant 打包命令、最后將apk包存放在指定目錄&#xff08;或者上傳指定ft…

對于線程并發模型與事件并發模型的思考

這里將以對話的形式進行&#xff1a; A&#xff1a; 普通的線程是可以被其他線程中斷掉的&#xff0c;而基于select、epoll的事件處理函數實際上是不可以被其他事件&#xff08;線程&#xff09;中斷的。 我這個理解對嗎&#xff1f; B&#xff1a; 圖片里的應該是對是否…

Cache 總結

這一文&#xff0c;讓我們分析一下&#xff0c;《淺談 Cache》 一文中的奇怪現象&#xff0c;事實上如今來看也并不奇怪了。在什么情況下 r1 和 r2 都為 0 呢&#xff1f;細致看代碼&#xff0c;你會發現&#xff0c;兩個線程分別被執行在不同的 CPU 核上&#xff0c;而且在線程…

c/c++常見類型轉換錯誤

文章目錄char轉int 高位符號擴展有符號int與無符號int比較關于一個bit的位域變量的取值范圍臨時變量溢出size_t死循環char轉int 高位符號擴展 int main() {char a 0x9A;int util;util (int)a;cout << a << endl;cout << util << endl;if (util >…

Javascript 裝載和執行

一兩個月前在淘寶內網里看到一個優化Javascript代碼的競賽&#xff0c;發現有不少的人對Javascript的執行和裝載的基礎并不懂&#xff0c;所以&#xff0c;從那天起我就想寫一篇文章&#xff0c;但一直耽擱了。 首先&#xff0c;我想說一下Javascript的裝載和執行。通常來說&am…

java sundry tips

1.關于Arrays 記得binarySearch方法返回的int 類型的數值的含義。 If the array contains multiple elements with the specified value, there is no guarantee which one will be found. 而且當查找數小于數組中任何一個數時返回-1 &#xff0c;當查找數大于數組中任何…

c++常見的10個類對象問題

文章目錄1、對象的淺復制2、構造函數中的操作符重載3、拷貝構造函數不能模板化4、析構函數未捕獲異常導致coredump5、構造函數拋出異常6、基類析構函數非虛導致內存泄漏7、刪除void*指針引發內存泄露8、成員函數尾部缺失const9、使用memset初始化class10、對象向下轉換失敗1、對…

Ubuntu 14.10 -- 異次元軟件世界

Ubuntu 14.10 中文桌面版/服務器正式版下載 - 華麗免費易于入門的 Linux 操作系統 [ 系統工具 - Linux // 2014-10-25 ]一說到 Linux&#xff0c;就不得不提目前最紅火的 Ubuntu 發行版了&#xff01;它擁有絢麗的界面&#xff0c;甚至跟以時尚為賣點的 Mac OSX 相比也有過之而…

maven 概念

這里maven倡導約定優于配置&#xff0c;maven的約定就是以下目錄結構src/main/java 下存放java類src/main/webapp 下存放頁面文件(需要手動創建)src/main/resources 下存放資源文件src/test/java 下存放單元測試代碼src/test/resources 下存放測試資源文件 Maven運行的生命周期…

System Design筆記:在線售票系統設計

文章目錄何為在線售票系統&#xff1f;系統目標和要求1、功能要求2、非功能性需求3、設計注意事項4、容量估算5、系統API1.SearchMovies2.ReserveSeats6、數據庫設計7、高級設計8、細節模塊設計9、流程服務器如何跟蹤所有尚未預訂的active預訂&#xff1f;服務器如何跟蹤所有等…

Response.Write具體介紹

問題一&#xff1a; Response.Write 后連接Response.Redirect &#xff0c;則Response.Write無法顯示&#xff0c;直接跳轉入Response.Redirect 的頁面。 解決方案&#xff1a; Response.Write("<script langugejavascript>alert(成功改動); window.location.hrefin…