溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

linux中 fork函數(shù)如何使用

發(fā)布時(shí)間:2021-07-14 15:36:39 來(lái)源:億速云 閱讀:200 作者:Leah 欄目:編程語(yǔ)言

本篇文章為大家展示了linux中 fork函數(shù)如何使用,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

【IT168 技術(shù)】  #include ;

  #include ;

  main ()

  {

  pid_t pid;

  pid=fork();

  if (pid < 0)

  printf("error in fork!");

  else if (pid == 0)

  printf("i am the child process, my process id is %dn",getpid());

  else

  printf("i am the parent process, my process id is %dn",getpid());

  }

  結(jié)果是

  [root@localhost c]# ./a.out

  i am the child process, my process id is 4286

  i am the parent process, my process id is 4285

  我就想不到為什么兩行都打印出來(lái)了,在我想來(lái),不管pid是多少,都應(yīng)該只有一行才對(duì)

  chg.s 回復(fù)于:2004-04-27 21:09:30

  要搞清楚fork的執(zhí)行過(guò)程,就必須先講清楚操作系統(tǒng)中的“進(jìn)程(process)”概念。一個(gè)進(jìn)程,主要包含三個(gè)元素:

  o. 一個(gè)可以執(zhí)行的程序;

  o. 和該進(jìn)程相關(guān)聯(lián)的全部數(shù)據(jù)(包括變量,內(nèi)存空間,緩沖區(qū)等等);

  o. 程序的執(zhí)行上下文(execution context)。

  不妨簡(jiǎn)單理解為,一個(gè)進(jìn)程表示的,就是一個(gè)可執(zhí)行程序的一次執(zhí)行過(guò)程中的一個(gè)狀態(tài)。操作系統(tǒng)對(duì)進(jìn)程的管理,典型的情況,是通過(guò)進(jìn)程表完成的。進(jìn)程表中的每一個(gè)表項(xiàng),記錄的是當(dāng)前操作系統(tǒng)中一個(gè)進(jìn)程的情況。對(duì)于單 CPU的情況而言,每一特定時(shí)刻只有一個(gè)進(jìn)程占用 CPU,但是系統(tǒng)中可能同時(shí)存在多個(gè)活動(dòng)的(等待執(zhí)行或繼續(xù)執(zhí)行的)進(jìn)程。

  一個(gè)稱為“程序計(jì)數(shù)器(program counter, pc)”的寄存器,指出當(dāng)前占用 CPU的進(jìn)程要執(zhí)行的下一條指令的位置。

  當(dāng)分給某個(gè)進(jìn)程的 CPU時(shí)間已經(jīng)用完,操作系統(tǒng)將該進(jìn)程相關(guān)的寄存器的值,保存到該進(jìn)程在進(jìn)程表中對(duì)應(yīng)的表項(xiàng)里面;把將要接替這個(gè)進(jìn)程占用 CPU的那個(gè)進(jìn)程的上下文,從進(jìn)程表中讀出,并更新相應(yīng)的寄存器(這個(gè)過(guò)程稱為“上下文交換(process context switch)”,實(shí)際的上下文交換需要涉及到更多的數(shù)據(jù),那和fork無(wú)關(guān),不再多說(shuō),主要要記住程序寄存器pc指出程序當(dāng)前已經(jīng)執(zhí)行到哪里,是進(jìn)程上下文的重要內(nèi)容,換出 CPU的進(jìn)程要保存這個(gè)寄存器的值,換入CPU的進(jìn)程,也要根據(jù)進(jìn)程表中保存的本進(jìn)程執(zhí)行上下文信息,更新這個(gè)寄存器)。

  好了,有這些概念打底,可以說(shuō)fork了。當(dāng)你的程序執(zhí)行到下面的語(yǔ)句:

  pid=fork();

  操作系統(tǒng)創(chuàng)建一個(gè)新的進(jìn)程(子進(jìn)程),并且在進(jìn)程表中相應(yīng)為它建立一個(gè)新的表項(xiàng)。新進(jìn)程和原有進(jìn)程的可執(zhí)行程序是同一個(gè)程序;上下文和數(shù)據(jù),絕大部分就是原進(jìn)程(父進(jìn)程)的拷貝,但它們是兩個(gè)相互獨(dú)立的進(jìn)程!此時(shí)程序寄存器pc,在父、子進(jìn)程的上下文中都聲稱,這個(gè)進(jìn)程目前執(zhí)行到fork調(diào)用即將返回(此時(shí)子進(jìn)程不占有CPU,子進(jìn)程的pc不是真正保存在寄存器中,而是作為進(jìn)程上下文保存在進(jìn)程表中的對(duì)應(yīng)表項(xiàng)內(nèi))。問(wèn)題是怎么返回,在父子進(jìn)程中就分道揚(yáng)鑣。

  父進(jìn)程繼續(xù)執(zhí)行,操作系統(tǒng)對(duì)fork的實(shí)現(xiàn),使這個(gè)調(diào)用在父進(jìn)程中返回剛剛創(chuàng)建的子進(jìn)程的pid(一個(gè)正整數(shù)),所以下面的if語(yǔ)句中pid<0, pid==0的兩個(gè)分支都不會(huì)執(zhí)行。所以輸出i am the parent process…

  子進(jìn)程在之后的某個(gè)時(shí)候得到調(diào)度,它的上下文被換入,占據(jù) CPU,操作系統(tǒng)對(duì)fork的實(shí)現(xiàn),使得子進(jìn)程中fork調(diào)用返回0。所以在這個(gè)進(jìn)程(注意這不是父進(jìn)程了哦,雖然是同一個(gè)程序,但是這是同一個(gè)程序的另外一次執(zhí)行,在操作系統(tǒng)中這次執(zhí)行是由另外一個(gè)進(jìn)程表示的,從執(zhí)行的角度說(shuō)和父進(jìn)程相互獨(dú)立)中pid=0。這個(gè)進(jìn)程繼續(xù)執(zhí)行的過(guò)程中,if語(yǔ)句中 pid<0不滿足,但是pid==0是true。所以輸出i am the child process…

  我想你比較困惑的就是,為什么看上去程序中互斥的兩個(gè)分支都被執(zhí)行了。在一個(gè)程序的一次執(zhí)行中,這當(dāng)然是不可能的;但是你看到的兩行輸出是來(lái)自兩個(gè)進(jìn)程,這兩個(gè)進(jìn)程來(lái)自同一個(gè)程序的兩次執(zhí)行。

  我的天,不知道說(shuō)明白了沒(méi)……

  zhaojinbo 回復(fù)于:2004-04-28 12:35:50

  fork 之后,操作系統(tǒng)會(huì)復(fù)制一個(gè)與父進(jìn)程完全相同的子進(jìn)程,雖說(shuō)是父子關(guān)系,但是在操作系統(tǒng)看來(lái),他們更像兄弟關(guān)系,這2個(gè)進(jìn)程共享代碼空間,但是數(shù)據(jù)空間是互相獨(dú)立的,子進(jìn)程數(shù)據(jù)空間中的內(nèi)容是父進(jìn)程的完整拷貝,指令指針也完全相同,但只有一點(diǎn)不同,如果fork成功,子進(jìn)程中 fork的返回值是0,父進(jìn)程中fork的返回值是子進(jìn)程的進(jìn)程號(hào),如果fork不成功,父進(jìn)程會(huì)返回錯(cuò)誤。

  可以這樣想象,2個(gè)進(jìn)程一直同時(shí)運(yùn)行,而且步調(diào)一致,在fork之后,他們分別作不同的工作,也就是分岔了。這也是fork為什么叫fork的原因。

  至于那一個(gè)最先運(yùn)行,可能與操作系統(tǒng)有關(guān),而且這個(gè)問(wèn)題在實(shí)際應(yīng)用中并不重要,如果需要父子進(jìn)程協(xié)同,可以通過(guò)原語(yǔ)的辦法解決。

  sniper 回復(fù)于:2004-04-28 22:11:15

  哦,偶明白了,在程序段里用了fork();之后程序出了分岔,派生出了兩個(gè)進(jìn)程。具體哪個(gè)先運(yùn)行就看該系統(tǒng)的調(diào)度算法了。

  在這里,我們可以這么認(rèn)為,在運(yùn)行到"pid=fork();"時(shí)系統(tǒng)派生出一個(gè)跟主程序一模一樣的子進(jìn)程。該進(jìn)程的"pid=fork();"一句中pid得到的就是子進(jìn)程本身的 pid;子進(jìn)程結(jié)束后,父進(jìn)程的"pid=fork();"中pid得到的就是父進(jìn)程本身的pid。因此改程序有兩行輸出。

  注:此處不準(zhǔn)確,在子進(jìn)程中pid的值為0,通過(guò)getpid可以獲取子進(jìn)程的進(jìn)程id;在父進(jìn)程中pid為父進(jìn)程編號(hào)。

  勘誤:父進(jìn)程中的pid值為子進(jìn)程進(jìn)程號(hào),只有父進(jìn)程執(zhí)行的getpid()才是他自己的進(jìn)程號(hào)。寒,徹底的in了

  jjl3 回復(fù)于:2004-07-14 11:43:20

  我做如下修改

  #include ;

  #include ;

  main ()

  {

  pid_t pid;

  printf("fork!"); // printf("fork!n");

  pid=fork();

  if (pid < 0)

  printf("error in fork!");

  else if (pid == 0)

  printf("i am the child process, my process id is %dn",getpid());

  else

  printf("i am the parent process, my process id is %dn",getpid());

  }

  結(jié)果是

  [root@localhost c]# ./a.out

  fork!i am the child process, my process id is 4286

  fork!i am the parent process, my process id is 4285

  但我改成printf("fork!n");后,結(jié)果是

  [root@localhost c]# ./a.out

  fork!

  i am the child process, my process id is 4286

  i am the parent process, my process id is 4285

  為什么只有一個(gè)fork!打印出來(lái)了?上一個(gè)為什么有2個(gè)?

  bashfulboy 回復(fù)于:2004-07-14 22:10:52

  我也來(lái)一下:

  wujiajia 的理解有些錯(cuò)誤,

  printf("AAAAAAAA");//print 一次; 這里會(huì)print 2次

  如果你將 printf("AAAAAA") 換成 printf("AAAAAAn") 那么就是只打印一次了。

  主要的區(qū)別是因?yàn)橛辛艘粋€(gè) n 回車符號(hào)

  這就跟Printf的緩沖機(jī)制有關(guān)了,printf某些內(nèi)容時(shí),操作系統(tǒng)僅僅是把該內(nèi)容放到了stdout的緩沖隊(duì)列里了,并沒(méi)有實(shí)際的寫到屏幕上

  但是,只要看到有 n 則會(huì)立即刷新stdout,因此就馬上能夠打印了。

  運(yùn)行了printf("AAAAAA") 后, AAAAAA 僅僅被放到了緩沖里,再運(yùn)行到fork時(shí),緩沖里面的 AAAAAA 被子進(jìn)程繼承了

  因此在子進(jìn)程度stdout緩沖里面就也有了 AAAAAA.

  所以,你最終看到的會(huì)是 AAAAAA 被printf了2次!!!!

  而運(yùn)行 printf("AAAAAAn")后, AAAAAA 被立即打印到了屏幕上,之后fork到的子進(jìn)程里的stdout緩沖里不會(huì)有 AAAAAA 內(nèi)容

  因此你看到的結(jié)果會(huì)是 AAAAAA 被printf了1次!!!!

  (精要)

  albcamus 回復(fù)于:2005-03-08 15:56:11

  >;>;派生子進(jìn)程的pid變量并沒(méi)有被改變是什么意思 對(duì)于子進(jìn)程來(lái)講pid不就是0嗎

  1,派生子進(jìn)程的進(jìn)程,即父進(jìn)程,其pid不變;

  2,對(duì)子進(jìn)程來(lái)說(shuō),fork返回給它0,但它的pid絕對(duì)不會(huì)是0;之所以fork返回0給它,是因?yàn)樗S時(shí)可以調(diào)用getpid()來(lái)獲取自己的pid;

  3,樓上的樓上的你的觀點(diǎn)是對(duì)的,fork之后夫子進(jìn)程除非采用了同步手段,否則不能確定誰(shuí)先運(yùn)行,也不能確定誰(shuí)先結(jié)束。認(rèn)為子進(jìn)程結(jié)束后父進(jìn)程才從fork返回的,這是不對(duì)的,fork不是這樣的,vfork才這樣。VFORK調(diào)用結(jié)束后,父進(jìn)程處于非可中斷狀態(tài),直到子進(jìn)程運(yùn)行結(jié)束返回。

上述內(nèi)容就是linux中 fork函數(shù)如何使用,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI