fork vfork exit _exit (转)
原文地址:http://hi.baidu.com/ikaruga11/blog/item/fb6d75725a8d8d148701b080.html
APUE上的一個(gè)例子:
example1 (forkt.c ):
#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int glob = 5;
int main()
{
??????? int var=10;
??????? pid_t pid;
??????? printf("befork vfork\n");
??????? if((pid = fork()) < 0){
??????????????? printf("error\n");
??????????????? exit(1);
??????? }else if(pid == 0){
??????????????? glob++;
??????????????? var++;
??????????????? _exit(0);
??????? }
??????? printf("pid = %d, glob = %d, var = %d",getpid(), glob,var);
??????? exit(0);
}
執(zhí)行
./forkt.c
./forkt.c > temp.out
將分別輸出什么呢?
為了找出為什么會(huì)輸出如上內(nèi)容,以及fork vfork exit _exit的區(qū)別,于是改造上面的代碼
example2:(省略了其他同上相同的代碼)
??????? printf("befork vfork\n");
??????? if((pid = fork()) < 0){
??????????????? printf("error\n");
??????????????? exit(1);
??????? }else if(pid == 0){
??????????????? glob++;
??????????????? var++;
??????????????? exit(0);
??????? }
??????? printf("pid = %d, glob = %d, var = %d",getpid(), glob,var);
??????? _exit(0);
執(zhí)行
./forkt.c
./forkt.c > temp.out
將分別輸出什么呢?
example3:(省略了其他同上相同的代碼)
??????? printf("befork vfork\n");
??????? if((pid = vfork()) < 0){
??????????????? printf("error\n");
??????????????? exit(1);
??????? }else if(pid == 0){
??????????????? glob++;
??????????????? var++;
??????????????? _exit(0);
??????? }
??????? printf("pid = %d, glob = %d, var = %d",getpid(), glob,var);
??????? exit(0);
執(zhí)行
./forkt.c
./forkt.c > temp.out
將分別輸出什么呢?
example4:(省略了其他同上相同的代碼)
??????? printf("befork vfork\n");
??????? if((pid = vfork()) < 0){
??????????????? printf("error\n");
??????????????? exit(1);
??????? }else if(pid == 0){
??????????????? glob++;
??????????????? var++;
??????????????? exit(0);
??????? }
??????? printf("pid = %d, glob = %d, var = %d",getpid(), glob,var);
??????? _exit(0);
./forkt.c
./forkt.c > temp.out
將分別輸出什么呢?
先把幾個(gè)概念縷一縷:
?? fork: 子進(jìn)程擁有父進(jìn)程的數(shù)據(jù)段、堆和棧的副本,父進(jìn)程和子進(jìn)程共享正文段。但現(xiàn)在很多實(shí)現(xiàn)卻并不是將父進(jìn)程的數(shù)據(jù)段、堆棧段進(jìn)行完全拷貝,而是采用寫時(shí)復(fù)制(copy-on-write),內(nèi)核將其標(biāo)記為只讀,(典型的頁(yè)式虛存)只有父進(jìn)程或子進(jìn)程對(duì)這些區(qū)域進(jìn)行修改時(shí)內(nèi)核才真正將那一頁(yè)進(jìn)行拷貝,從物理上分離開。
?? vfork:由于在vfork后經(jīng)常是跟著一個(gè)exec執(zhí)行一個(gè)新的程序不會(huì)在用到原來(lái)的地址空間,所以vfork的子進(jìn)程在調(diào)用exec或exit之前是在父進(jìn)程的空間里運(yùn)行的,這樣對(duì)于頁(yè)式虛存效率很高。另外,vfork的子進(jìn)程總是先與父進(jìn)程執(zhí)行,但是子進(jìn)程不能依賴與父進(jìn)程的執(zhí)行否則產(chǎn)生死鎖。
exit(0):根據(jù)實(shí)現(xiàn)的不同而不同,一般是刷新I/O緩沖區(qū),關(guān)閉所有I/O標(biāo)準(zhǔn)流(APUE上如是說(shuō),但是我在linux下驗(yàn)證的結(jié)果應(yīng)該是沒有關(guān)閉),一般現(xiàn)在的I/O庫(kù)函數(shù)在關(guān)閉I/O流方面不自找麻煩了。
_exit(0):不刷新I/O緩沖區(qū)
標(biāo)準(zhǔn)I/O庫(kù):
標(biāo)準(zhǔn)I/O庫(kù)是帶緩存的,如果標(biāo)準(zhǔn)輸出是連接到終端設(shè)備,則它是行緩沖的,否則是全緩沖的。行緩沖在接收到一個(gè)換行符才進(jìn)行刷新,而全緩沖在緩沖區(qū)滿或者程序在執(zhí)行exit退出后在執(zhí)行緩沖區(qū)刷新
好了 ,現(xiàn)在我們來(lái)看看上面的例子到底輸出什么東東了
example1:
執(zhí)行:./forkt.c
交互方式執(zhí)行,則是行緩沖, befork vfork后跟一個(gè)換行符\n,則刷新緩沖區(qū)輸出 befork vfork,然后fork一個(gè)子進(jìn)程,父子進(jìn)程分別運(yùn)行在不同的存儲(chǔ)空間,子進(jìn)程執(zhí)行_exit()退出,不刷新緩沖區(qū),父進(jìn)程執(zhí)行最后一個(gè)printf,但由于沒有遇到\n,所以并不立即輸出,在執(zhí)行exit(0)后刷新緩沖區(qū),此時(shí)輸出
pid =6724, glob = 5, var =10
執(zhí)行:./forkt.c > temp.out
非交互方式,則是全緩沖,首先執(zhí)行printf("befork vfork\n")此時(shí)并不輸出,而是緩存在緩沖區(qū),然后fork一個(gè)子進(jìn)程,父子進(jìn)程分別運(yùn)行在不同的存儲(chǔ)空間,拷貝一份父進(jìn)程中緩沖區(qū)的befork vfork\n 到子進(jìn)程,子進(jìn)程執(zhí)行_exit()退出,不刷新緩沖區(qū),父進(jìn)程執(zhí)行最后一個(gè)printf,也緩存起來(lái)并不立即輸出,在執(zhí)行exit(0)后刷新緩沖區(qū),此時(shí)輸出全部輸出
cat > temp.out 輸出如下:
befork vfork
pid =6731, glob = 5, var =10
example2:
執(zhí)行:./forkt.c
交互方式執(zhí)行,則是行緩沖, befork vfork后跟一個(gè)換行符\n,則刷新緩沖區(qū)輸出 befork vfork,然后fork一個(gè)子進(jìn)程,父子進(jìn)程分別運(yùn)行在不同的存儲(chǔ)空間,子進(jìn)程執(zhí)行exit()刷新緩沖區(qū)退出,父進(jìn)程執(zhí)行最后一個(gè) printf,但由于沒有遇到\n,所以并不立即輸出,在執(zhí)行_exit(0)后由于不刷新緩沖區(qū)而退出,所以最后一個(gè)printf內(nèi)容并不輸出。所以
執(zhí)行:./forkt.c
befork vfork
執(zhí)行:./forkt.c > temp.out
非交互方式,則是全緩沖,首先執(zhí)行printf("befork vfork\n")此時(shí)并不輸出,而是緩存在緩沖區(qū),然后fork一個(gè)子進(jìn)程,父子進(jìn)程分別運(yùn)行在不同的存儲(chǔ)空間,同時(shí)拷貝一份父進(jìn)程中緩沖區(qū)的befork vfork\n 到子進(jìn)程,子進(jìn)程執(zhí)行exit()刷新緩沖區(qū)退出,此時(shí)輸出befork vfork\n ,父進(jìn)程執(zhí)行最后一個(gè)printf,也緩存起來(lái)并不立即輸出,在執(zhí)行_exit(0)后由于不刷新緩沖區(qū)而退出,因此輸出
cat > temp.out 輸出如下:
befork vfork
example3:
執(zhí)行:./forkt.c
交互方式執(zhí)行,則是行緩沖, befork vfork后跟一個(gè)換行符\n,則刷新緩沖區(qū)輸出 befork vfork,然后vfork一個(gè)子進(jìn)程,父子進(jìn)程運(yùn)行在相同的存儲(chǔ)空間,子進(jìn)程執(zhí)行_exit()不刷新緩沖區(qū)退出,父進(jìn)程執(zhí)行最后一個(gè) printf,但由于沒有遇到\n,所以并不立即輸出,在執(zhí)行exit(0)后刷新緩沖區(qū)而退出,所以最后一個(gè)printf內(nèi)容輸出。所以
執(zhí)行:./forkt.c
befork vfork
pid =6802, glob = 6, var =11
執(zhí)行:./forkt.c > temp.out
非交互方式,則是全緩沖,首先執(zhí)行printf("befork vfork\n")此時(shí)并不輸出,而是緩存在緩沖區(qū),然后vfork一個(gè)子進(jìn)程,父子進(jìn)程運(yùn)行在相同的存儲(chǔ)空間,子進(jìn)程執(zhí)行_exit()不刷新緩沖區(qū)退出,父進(jìn)程執(zhí)行最后一個(gè)printf,也緩存起來(lái)并不立即輸出,在執(zhí)行exit(0)刷新緩沖區(qū)而退出,因此輸出
cat > temp.out 輸出如下:
befork vfork
pid =6808, glob = 6, var =11
example4:
執(zhí)行:./forkt.c
befork vfork
pid =6802, glob = 6, var =11
執(zhí)行:./forkt.c > temp.out
cat > temp.out 輸出如下:
befork vfork
pid =6808, glob = 6, var =11
?
另外
簡(jiǎn)單的說(shuō),exit函數(shù)將終止調(diào)用進(jìn)程。在退出程序之前,所有文件關(guān)閉,緩沖輸出內(nèi)容將刷新定義,并調(diào)用所有已刷新的“出口函數(shù)”(由atexit定義)。 _exit:該函數(shù)是由Posix定義的,不會(huì)運(yùn)行exit handler和signal handler,在UNIX系統(tǒng)中不會(huì)flush標(biāo)準(zhǔn)I/O流。 簡(jiǎn)單的說(shuō),_exit終止調(diào)用進(jìn)程,但不關(guān)閉文件,不清除輸出緩存,也不調(diào)用出口函數(shù)。 共同: 不管進(jìn)程是如何終止的,內(nèi)核都會(huì)關(guān)閉進(jìn)程打開的所有file descriptors,釋放進(jìn)程使用的memory! note: 在由‘fork()’創(chuàng)建的子進(jìn)程分支里,正常情況下使用‘exit()’是不正確的,這是 因?yàn)槭褂盟鼤?huì)導(dǎo)致標(biāo)準(zhǔn)輸入輸出的緩沖區(qū)被清空兩次,而且臨時(shí)文件被出乎意料的刪除(譯者注:臨時(shí)文件由tmpfile函數(shù)創(chuàng)建在系統(tǒng)臨時(shí)目錄下,文件名由系統(tǒng)隨機(jī)生成)。 在C++程序中情況會(huì)更糟,因?yàn)殪o態(tài)目標(biāo)(static objects)的析構(gòu)函數(shù)(destructors)可以被錯(cuò)誤地執(zhí)行。 還有一些特殊情況,比如守護(hù)程序,它們的父進(jìn)程需要調(diào)用‘_exit()’而不是子進(jìn)程;適用于絕大多數(shù)情況的基本規(guī)則是,‘exit()’在每一次進(jìn)入‘main’函數(shù)后只調(diào)用一次。在由‘vfork()’創(chuàng)建的子進(jìn)程分支里,‘exit()’的使用將更加危險(xiǎn),因?yàn)樗鼘⒂绊?父進(jìn)程的狀態(tài)
轉(zhuǎn)載于:https://www.cnblogs.com/Myhsg/archive/2009/09/07/1562080.html
總結(jié)
以上是生活随笔為你收集整理的fork vfork exit _exit (转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET MVC V2 Previ
- 下一篇: 佛祖说出的爱情箴言