fork函數(shù)的2個(gè)返回值說明_第1頁
fork函數(shù)的2個(gè)返回值說明_第2頁
fork函數(shù)的2個(gè)返回值說明_第3頁
fork函數(shù)的2個(gè)返回值說明_第4頁
fork函數(shù)的2個(gè)返回值說明_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、fork簡介:fork英文原意是分岔,分支”的意思,而在操作系統(tǒng)中,乃是著名的Unix(或類Unix,如Linux.Minix)中用于創(chuàng)建子進(jìn)程的系統(tǒng)調(diào)用。【NOTE1】fork()的作用是什么?換句話說,你用fork()的目的是什么?一一是為了產(chǎn)生一個(gè)新的進(jìn)程,地球人都知道:)產(chǎn)生一個(gè)什么樣的進(jìn)程?一一和你本來調(diào)用fork()的那個(gè)進(jìn)程基本一樣的進(jìn)程,其實(shí)就是你原來進(jìn)程的副本;真的完全一樣嗎?當(dāng)然不能完全一樣,你要兩個(gè)除了pid之外其它一模一樣的進(jìn)程干什么,就算memory再多也不用這么擺譜吧?哪里不一樣?一一當(dāng)然最重要的是fork()之后執(zhí)行的代碼不一樣,youknow,iknow:)怎么

2、實(shí)現(xiàn)呢?如果是Windows,它會(huì)讓你在fork()里面提供一大堆東西,指明這個(gè)那個(gè)什么的我用的是unix啊一一所以很簡單,unix會(huì)讓兩個(gè)進(jìn)程(不錯(cuò),原來是一個(gè),unix替你復(fù)制了一個(gè),現(xiàn)在有兩個(gè))在fork()之后產(chǎn)生不同:返回值不同。其中一個(gè)進(jìn)程(使用新的pid)里面的fork()返回零,這個(gè)進(jìn)程就是子進(jìn)程”;而另一個(gè)進(jìn)程(使用原來的pid)中的fork()返回前面那個(gè)子進(jìn)程的pid,他自己被稱為“父進(jìn)程”然后呢?一一寫代碼的人又不笨,當(dāng)然就根據(jù)返回值是否非零來判斷了,現(xiàn)在我是在子進(jìn)程里面呢,還是在父進(jìn)程里面?在子進(jìn)程里面就執(zhí)行子進(jìn)程該執(zhí)行的代碼,在父進(jìn)程里面就執(zhí)行父進(jìn)程的代碼有鐵桿wi

3、ndowsfans借此說明,windows好啊,子進(jìn)程用子進(jìn)程的代碼,父進(jìn)程用父進(jìn)程的,你unix笨了吧,子進(jìn)程包含父進(jìn)程、子進(jìn)程的代碼,父進(jìn)程包含父進(jìn)程子進(jìn)程的代碼,豈不是多占用內(nèi)存了嗎?據(jù)我所知,unix代碼段都是可重入代碼,也就是說,進(jìn)程復(fù)制,并不復(fù)制代碼段,若干個(gè)進(jìn)程共享同一代碼段,增加的只是全局共享數(shù)據(jù)和對(duì)文件描述符的引用等,另外就是堆棧。你一個(gè)代碼長達(dá)10M的進(jìn)程,fork()出三四個(gè)子進(jìn)程,只是增加一點(diǎn)內(nèi)存占用(如果你沒有使用很多全局變量的話),而不是占用40M以上的內(nèi)存。【NOTE2】程序從fork開始分支(稱分支不準(zhǔn)確),一路是主進(jìn)程pid0(pid是子進(jìn)程ID)路是子進(jìn)程p

4、id=0自此分成兩個(gè)任務(wù)其實(shí)fork的時(shí)候已經(jīng)兩個(gè)分支了,數(shù)據(jù)段被復(fù)制了一份,因此pid有兩份執(zhí)行pid=fork()時(shí),返回值賦給pid在兩個(gè)進(jìn)程中運(yùn)行,fork會(huì)返回給父進(jìn)程的那個(gè)0的值,告訴調(diào)用者新建進(jìn)程的pid子進(jìn)程的fork返回值是0更不用說if.else的比較也是在兩個(gè)進(jìn)程中都做的了【NOTE3】fork的精辟剖析程序如下:#include;#include;main()pid_tpid;pid=fork();if(pidpid_tfork();當(dāng)一個(gè)進(jìn)程調(diào)用了fork以后,系統(tǒng)會(huì)創(chuàng)建一個(gè)子進(jìn)程這個(gè)子進(jìn)程和父進(jìn)程不同的地方只有他的進(jìn)程ID和父進(jìn)程ID,其他的都是一樣就象父進(jìn)程克?。?/p>

5、clone)自己一樣當(dāng)然創(chuàng)建兩個(gè)一模一樣的進(jìn)程是沒有意義的為了區(qū)分父進(jìn)程和子進(jìn)程,我們必須跟蹤fork的返回值.當(dāng)fork掉用失敗的時(shí)候(內(nèi)存不足或者是用戶的最大進(jìn)程數(shù)已到)fork返回-1,否則fork的返回值有重要的作用對(duì)于父進(jìn)程fork返回子進(jìn)程的ID,而對(duì)于fork子進(jìn)程返回0我們就是根據(jù)這個(gè)返回值來區(qū)分父子進(jìn)程的.父進(jìn)程為什么要?jiǎng)?chuàng)建子進(jìn)程呢?前面我們已經(jīng)說過了Linux是一個(gè)多用戶操作系統(tǒng),在同一時(shí)間會(huì)有許多的用戶在爭奪系統(tǒng)的資源.有時(shí)進(jìn)程為了早一點(diǎn)完成任務(wù)就創(chuàng)建子進(jìn)程來爭奪資源.一旦子進(jìn)程被創(chuàng)建,父子進(jìn)程一起從fork處繼續(xù)執(zhí)行,相互競爭系統(tǒng)的資源.有時(shí)候我們希望子進(jìn)程繼續(xù)執(zhí)行,而

6、父進(jìn)程阻塞,直到子進(jìn)程完成任務(wù).這個(gè)時(shí)候我們可以調(diào)用wait或者waitpid系統(tǒng)調(diào)用.總結(jié)一下有三:派生子進(jìn)程的進(jìn)程,即父進(jìn)程,其pid不變;對(duì)子進(jìn)程來說,fork返回給它0,但它的pid絕對(duì)不會(huì)是0;之所以fork返回0給它,是因?yàn)樗S時(shí)可以調(diào)用getpid()來獲取自己的pid;fork之后父子進(jìn)程除非采用了同步手段,否則不能確定誰先運(yùn)行,也不能確定誰先結(jié)束。認(rèn)為子進(jìn)程結(jié)束后父進(jìn)程才從fork返回的,這是不對(duì)的,fork不是這樣的,vfork才這樣?!綨OTE4】首先必須有一點(diǎn)要清楚,函數(shù)的返回值是儲(chǔ)存在寄存器eax中的。其次,當(dāng)fork返回時(shí),新進(jìn)程會(huì)返回0是因?yàn)樵诔跏蓟蝿?wù)結(jié)構(gòu)時(shí),將

7、eax設(shè)置為0;在fork中,把子進(jìn)程加入到可運(yùn)行的隊(duì)列中,由進(jìn)程調(diào)度程序在適當(dāng)?shù)臅r(shí)機(jī)調(diào)度運(yùn)行。也就是從此時(shí)開始,當(dāng)前進(jìn)程分裂為兩個(gè)并發(fā)的進(jìn)程。無論哪個(gè)進(jìn)程被調(diào)度運(yùn)行,都將繼續(xù)執(zhí)行fork函數(shù)的剩余代碼,執(zhí)行結(jié)束后返回各自的值。【NOTE5】對(duì)于fork來說,父子進(jìn)程共享同一段代碼空間,所以給人的感覺好像是有兩次返回,其實(shí)對(duì)于調(diào)用fork的父進(jìn)程來說,如果fork出來的子進(jìn)程沒有得到調(diào)度,那么父進(jìn)程從fork系統(tǒng)調(diào)用返回,同時(shí)分析sys_fork知道,fork返回的是子進(jìn)程的id。再看fork出來的子進(jìn)程,由copy_process函數(shù)可以看出,子進(jìn)程的返回地址為ret_from_fork(和

8、父進(jìn)程在同一個(gè)代碼點(diǎn)上返回),返回值直接置為0。所以當(dāng)子進(jìn)程得到調(diào)度的時(shí)候,也從fork返回,返回值為0。關(guān)鍵注意兩點(diǎn):l.fork返回后,父進(jìn)程或子進(jìn)程的執(zhí)行位置。(首先會(huì)將當(dāng)前進(jìn)程eax的值做為返回值)2.兩次返回的pid存放的位置(eax中)進(jìn)程調(diào)用copy_process得到lastpid的值(放入eax中,fork正常返回后,父進(jìn)程中返回的就是lastpid)子進(jìn)程任務(wù)狀態(tài)段tss的eax被設(shè)置成0,fork.c中p-tss.eax=0;(如果子進(jìn)程要執(zhí)行就需要進(jìn)程切換,當(dāng)發(fā)生切換時(shí),子進(jìn)程tss中的eax值就調(diào)入eax寄存器,子進(jìn)程執(zhí)行時(shí)首先會(huì)將eax的內(nèi)容做為返回值)當(dāng)子進(jìn)程開始

9、執(zhí)行時(shí),copy_process返回eax的值。fork()后,就是兩個(gè)任務(wù)同時(shí)進(jìn)行,父進(jìn)程用他的tss,子進(jìn)程用自己的tss,在切換時(shí),各用各的eax中的值.所以,“一次調(diào)用兩次返回”是2個(gè)不同的進(jìn)程!看這一句:pid=fork()當(dāng)執(zhí)行這一句時(shí),當(dāng)前進(jìn)程進(jìn)入fork()運(yùn)行,此時(shí),fork()內(nèi)會(huì)用一段嵌入式匯編進(jìn)行系統(tǒng)調(diào)用:int0 x80(具體代碼可參見內(nèi)核版本0.11的unistd.h文件的133行_syscall0函數(shù))。這時(shí)進(jìn)入內(nèi)核根據(jù)此前寫入eax的系統(tǒng)調(diào)用功能號(hào)便會(huì)運(yùn)行sys_fork系統(tǒng)調(diào)用。接著,sys_fork中首先會(huì)調(diào)用C函數(shù)find_empty_process產(chǎn)生一

10、個(gè)新的進(jìn)程,然后會(huì)調(diào)用C函數(shù)copy_process將父進(jìn)程的內(nèi)容復(fù)制給子進(jìn)程,但是子進(jìn)程tss中的eax值賦值為0(這也是為什么子進(jìn)程中返回0的原因),當(dāng)賦值完成后,copy_process會(huì)返回新進(jìn)程(該子進(jìn)程)的pid,這個(gè)值會(huì)被保存到eax中。這時(shí)子進(jìn)程就產(chǎn)生了,此時(shí)子進(jìn)程與父進(jìn)程擁有相同的代碼空間,程序指針寄存器eip指向相同的下一條指令地址,當(dāng)fork正常返回調(diào)用其的父進(jìn)程后,因?yàn)閑ax中的值是新創(chuàng)建的子進(jìn)程號(hào),所以,fork()返回子進(jìn)程號(hào),執(zhí)行else(pid0);當(dāng)產(chǎn)生進(jìn)程切換運(yùn)行子進(jìn)程時(shí),首先會(huì)恢復(fù)子進(jìn)程的運(yùn)行環(huán)境即裝入子進(jìn)程的tss任務(wù)狀態(tài)段,其中的eax值(copy_p

11、rocess中置為0)也會(huì)被裝入eax寄存器,所以,當(dāng)子進(jìn)程運(yùn)行時(shí),fork返回的是0執(zhí)行if(pid=0)?!綨OTE5】理解它關(guān)鍵在于理解堆棧的切換和壓棧,彈棧!關(guān)于子進(jìn)程的返回:子進(jìn)程復(fù)制了父進(jìn)程的棧內(nèi)容,從高到低SSESPEFLAGSCSEIP-此是int0 x80的下一條指令,也是子進(jìn)程開始執(zhí)行的地方DSESFSEDXECXEBXGSESIEDIEBPEAX(0)由于EAX=0,所以子進(jìn)程返回0給fork.注:新進(jìn)程的用戶棧設(shè)為其父進(jìn)程的用戶棧(最后彈出的SS,ESP)。如果父子進(jìn)程以copy_on_write方式共用用戶堆棧(Linux之下就是這樣的),而且在此之前父進(jìn)程修改了該堆

12、棧(如果父進(jìn)程先返回,這幾乎是肯定的),那么,系統(tǒng)已經(jīng)為父進(jìn)程創(chuàng)建了該用戶棧的副本,父進(jìn)程原來的用戶棧留給了子進(jìn)程。那么新進(jìn)程的系統(tǒng)棧已經(jīng)清空,新進(jìn)程回到了用戶態(tài),返回到了函數(shù)fork。【NOTE6】關(guān)于fork的討論與評(píng)價(jià):fork好不好?相比其他操作系統(tǒng)如Windows.Windows會(huì)有諸如CreateProcess這樣的函數(shù)來創(chuàng)建一個(gè)與生俱來兩手空空的獨(dú)立的新進(jìn)程。然后還有一大堆參數(shù),指手畫腳的告訴你這個(gè)那個(gè)是什么。煩K.I.S.S.(Keepitsimple,stupid.)是Unix的至高原則。fork起源于Unix操作系統(tǒng)。那是貝爾實(shí)驗(yàn)室的K&R(這兩人是Unix和C語言之父)的一項(xiàng)天才發(fā)明Linux由于與生俱來就與Unix血濃于水,所以繼承了它的這個(gè)天才發(fā)明。這種方法效率是很高的。因?yàn)閺?fù)制的代價(jià)是很低的。在計(jì)算機(jī)網(wǎng)絡(luò)的實(shí)現(xiàn)中,以及在client/server系統(tǒng)中的server一方的實(shí)現(xiàn)中,fork常常是最自然,最有效,最適宜的手段。很多人甚至懷疑,到底是先有fork還是

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論