fork()与pid
寫在前面:最近學(xué)到Linux的進程間通信,發(fā)現(xiàn)以前學(xué)的進程有點忘了,就找了一些博客來看,這篇博客講的挺簡單易懂的,就搬運來當(dāng)筆記了,原文也是轉(zhuǎn)載的找不到出處,有知道的可以告訴我,我再加上。
fork調(diào)用的一個奇妙之處就是它僅僅被調(diào)用一次,卻能夠返回兩次,它可能有三種不同的返回值:
??? 1)在父進程中,fork返回新創(chuàng)建子進程的進程ID;
??? 2)在子進程中,fork返回0;
??? 3)如果出現(xiàn)錯誤,fork返回一個負值;
創(chuàng)建新進程成功后,系統(tǒng)中出現(xiàn)兩個基本完全相同的進程,這兩個進程執(zhí)行沒有固定的先后順序,哪個進程先執(zhí)行要看系統(tǒng)的進程調(diào)度策略。此時,兩個進程都從fork開始往下執(zhí)行,只是pid不同。
????有人可能疑惑為什么不是從#include處開始復(fù)制代碼的?
看下圖:
????? 上圖表示一個含有fork的程序,而fork語句可以看成將程序切為A、B兩個部分。然后整個程序會如下運行:
????? step1、設(shè)由shell直接執(zhí)行程序,生成了進程P。P執(zhí)行完P(guān)art. A的所有代碼。
????? step2、當(dāng)執(zhí)行到pid = fork();時,P啟動一個進程Q,Q是P的子進程,和P是同一個程序的進程。Q繼承P的所有變量、環(huán)境變量、程序計數(shù)器的當(dāng)前值。
????? step3、在P進程中,fork()將Q的PID返回給變量pid,并繼續(xù)執(zhí)行Part. B的代碼。
????? step4、在進程Q中,將0賦給pid,并繼續(xù)執(zhí)行Part. B的代碼。
????? 這里有三個點非常關(guān)鍵:
??????1、P執(zhí)行了所有程序,而Q只執(zhí)行了Part. B,即fork()后面的程序。(這是因為Q繼承了P的PC-程序計數(shù)器)
????? 2、Q繼承了fork()語句執(zhí)行時當(dāng)前的環(huán)境,而不是程序的初始環(huán)境。
????? 3、P中fork()語句啟動子進程Q,并將Q的PID返回,而Q中的fork()語句不啟動新進程,僅將0返回。
#include <unistd.h>?
#include <sys/types.h>
main ()?
{?
???????? pid_t pid;?
???????? printf("hello!\n");??
???????? pid=fork();
???????? if (pid < 0)?
???????????????? printf("error in fork!");?
???????? else if (pid == 0)?
???????????????? printf("i am the child process, my process id is %d\n ",getpid());
???????? else?
???????????????? printf("i am the parent process, my process id is %d\n",getpid());
???????? printf("bye!\n");
}?
這里可以看出parent process執(zhí)行了printf("hello!\n");? 而child process 沒有執(zhí)行printf("hello!\n");?
有一個讓人很迷惑的例子:
#include <unistd.h>
#include <sys/types.h>
main ()?
{?
???????? pid_t pid;?
???????? printf("fork!");????//printf("fork!\n")
???????? pid=fork();?
???????? if (pid < 0)?
???????????????? printf("error in fork!\n");?
???????? else if (pid == 0)?
???????????????? printf("i am the child process, my process id is %d\n",getpid());
???????? else?
???????????????? printf("i am the parent process, my process id is %d\n",getpid());
}?
此時打印輸出了兩個fork!這不免讓人以為是child process從#include處開始執(zhí)行,所以也執(zhí)行了printf("fork!");?語句。
其實不然,出現(xiàn)這種問題的原因在于:
這就跟Printf的緩沖機制有關(guān)了,printf某些內(nèi)容時,操作系統(tǒng)僅僅是把該內(nèi)容放到了stdout的緩沖隊列里了,并沒有實際的寫到屏幕上 。但是,只要看到有\(zhòng)n, 則會立即刷新stdout,因此就馬上能夠打印了.
mian函數(shù)(parent process)運行了printf("fork!") 后, "fork!"僅僅被放到了緩沖里,再運行到fork時,緩沖里面的 AAAAAA 被子進程(child process)繼承了,因此在子進程度stdout緩沖里面就也有了"fork!"。所以,你最終看到的會是?"fork!"?被printf了2次!!!!?
而mian函數(shù)(parent process)運行 printf("fork!\n")后,"fork!"?被立即打印到了屏幕上,之后fork到的子進程(child process)里的stdout緩沖里不會有"fork!"內(nèi)容 因此你看到的結(jié)果會是"fork!"?被printf了1次!!!!?
總結(jié)
以上是生活随笔為你收集整理的fork()与pid的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: main函数的参数详解,它们是何时何处传
- 下一篇: 检测子进程的结束返回状态,status的