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