版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024-2030年新版中國輸變電設(shè)備器材項(xiàng)目可行性研究報(bào)告
- 2024-2030年新版中國不銹鋼焊接式烘筒項(xiàng)目可行性研究報(bào)告
- 2024-2030年全球及中國間溴苯甲醚市場需求前景及發(fā)展趨勢預(yù)測報(bào)告
- 2024-2030年全球及中國蒸壓加氣混凝土(AAC)磚塊行業(yè)運(yùn)行狀況及需求前景預(yù)測報(bào)告
- 2024-2030年全球及中國納米劃痕測試儀行業(yè)競爭格局及前景趨勢預(yù)測報(bào)告
- 2024-2030年全球及中國直接胎壓監(jiān)測系統(tǒng)行業(yè)應(yīng)用前景及需求規(guī)模預(yù)測報(bào)告
- 2024-2030年全球及中國牙科器械架行業(yè)應(yīng)用前景及投資盈利預(yù)測報(bào)告
- 2024-2030年全球及中國油基平版印刷油墨行業(yè)發(fā)展現(xiàn)狀及未來前景趨勢預(yù)測報(bào)告
- 2024-2030年全球及中國吸頂式風(fēng)機(jī)盤管行業(yè)供需態(tài)勢及渠道策略研究報(bào)告
- 2024-2030年全球及中國三聚氰酸三烯丙酯(TAC)行業(yè)需求趨勢及前景動(dòng)態(tài)預(yù)測報(bào)告
- 猜猜哪是左哪是右課件
- 單層門式輕鋼結(jié)構(gòu)廠房施工組織設(shè)計(jì)
- 融資租賃租金計(jì)算模板
- DL5168-2023年110KV-750KV架空輸電線路施工質(zhì)量檢驗(yàn)及評(píng)定規(guī)程
- 詳細(xì)解讀公文格式
- (全冊(cè))教學(xué)設(shè)計(jì)(教案)新綱要云南省實(shí)驗(yàn)教材小學(xué)信息技術(shù)四年級(jí)第3冊(cè)全冊(cè)
- 農(nóng)產(chǎn)品市場營銷-東北農(nóng)業(yè)大學(xué)中國大學(xué)mooc課后章節(jié)答案期末考試題庫2023年
- EN81-41升降平臺(tái)歐洲標(biāo)準(zhǔn)
- 內(nèi)鏡下粘膜剝離術(shù)-課件
- 2024屆福建省泉州高考一模地理試題(解析版)
- 2023年06月深圳市坪山區(qū)機(jī)關(guān)事業(yè)單位公共輔助員適崗能力招考筆試題庫含答案解析
評(píng)論
0/150
提交評(píng)論