日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

fork、vfork、clone

發(fā)布時(shí)間:2023/11/30 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 fork、vfork、clone 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 概念

寫(xiě)時(shí)復(fù)制技術(shù)最初產(chǎn)生于Unix系統(tǒng),用于實(shí)現(xiàn)一種傻瓜式的進(jìn)程創(chuàng)建:當(dāng)發(fā)出fork(??)系統(tǒng)調(diào)用時(shí),內(nèi)核原樣復(fù)制父進(jìn)程的整個(gè)地址空間并把復(fù)制的那一份分配給子進(jìn)程。這種行為是非常耗時(shí)的,因?yàn)樗枰?#xff1a;

  • 為子進(jìn)程的頁(yè)表分配頁(yè)面
  • 為子進(jìn)程的頁(yè)分配頁(yè)面
  • 初始化子進(jìn)程的頁(yè)表
  • 把父進(jìn)程的頁(yè)復(fù)制到子進(jìn)程相應(yīng)的頁(yè)中

創(chuàng)建一個(gè)地址空間的這種方法涉及許多內(nèi)存訪問(wèn),消耗許多CPU周期,并且完全破壞了高速緩存中的內(nèi)容。在大多數(shù)情況下,這樣做常常是毫無(wú)意義的,因?yàn)樵S多子進(jìn)程通過(guò)裝入一個(gè)新的程序開(kāi)始它們的執(zhí)行,這樣就完全丟棄了所繼承的地址空間。

現(xiàn)在的Unix內(nèi)核(包括Linux),采用一種更為有效的方法稱之為寫(xiě)時(shí)復(fù)制(或COW)。這種思想相當(dāng)簡(jiǎn)單:父進(jìn)程和子進(jìn)程共享頁(yè)面而不是復(fù)制頁(yè)面。然而,只要頁(yè)面被共享,它們就不能被修改。無(wú)論父進(jìn)程和子進(jìn)程何時(shí)試圖寫(xiě)一個(gè)共享的頁(yè)面,就產(chǎn)生一個(gè)錯(cuò)誤,這時(shí)內(nèi)核就把這個(gè)頁(yè)復(fù)制到一個(gè)新的頁(yè)面中并標(biāo)記為可寫(xiě)。原來(lái)的頁(yè)面仍然是寫(xiě)保護(hù)的:當(dāng)其它進(jìn)程試圖寫(xiě)入時(shí),內(nèi)核檢查寫(xiě)進(jìn)程是否是這個(gè)頁(yè)面的唯一屬主;如果是,它把這個(gè)頁(yè)面標(biāo)記為對(duì)這個(gè)進(jìn)程是可寫(xiě)的。

?

2. Linux的fork()使用寫(xiě)時(shí)復(fù)制

????? 傳統(tǒng)的fork()系統(tǒng)調(diào)用直接把所有的資源復(fù)制給新創(chuàng)建的進(jìn)程。這種實(shí)現(xiàn)過(guò)于簡(jiǎn)單并且效率低下,因?yàn)樗截惖臄?shù)據(jù)或許可以共享(This approach is significantly na?ve and inefficient in that it copies much data that might otherwise be shared.)。更糟糕的是,如果新進(jìn)程打算立即執(zhí)行一個(gè)新的映像,那么所有的拷貝都將前功盡棄。Linux的fork()使用寫(xiě)時(shí)拷貝(copy-on-write)頁(yè)實(shí)現(xiàn)。寫(xiě)時(shí)拷貝是一種可以推遲甚至避免拷貝數(shù)據(jù)的技術(shù)。內(nèi)核此時(shí)并不復(fù)制整個(gè)進(jìn)程的地址空間,而是讓父子進(jìn)程共享同一個(gè)地址空間。只用在需要寫(xiě)入的時(shí)候才會(huì)復(fù)制地址空間,從而使各個(gè)進(jìn)行擁有各自的地址空間。也就是說(shuō),資源的復(fù)制是在需要寫(xiě)入的時(shí)候才會(huì)進(jìn)行,在此之前,只有以只讀方式共享。這種技術(shù)使地址空間上的頁(yè)的拷貝被推遲到實(shí)際發(fā)生寫(xiě)入的時(shí)候。在頁(yè)根本不會(huì)被寫(xiě)入的情況下---例如,fork()后立即執(zhí)行exec(),地址空間就無(wú)需被復(fù)制了。fork()的實(shí)際開(kāi)銷(xiāo)就是復(fù)制父進(jìn)程的頁(yè)表以及給子進(jìn)程創(chuàng)建一個(gè)進(jìn)程描述符。在一般情況下,進(jìn)程創(chuàng)建后都為馬上運(yùn)行一個(gè)可執(zhí)行的文件,這種優(yōu)化,可以避免拷貝大量根本就不會(huì)被使用的數(shù)據(jù)(地址空間里常常包含數(shù)十兆的數(shù)據(jù))。由于Unix強(qiáng)調(diào)進(jìn)程快速執(zhí)行的能力,所以這個(gè)優(yōu)化是很重要的。

COW技術(shù)初窺:

?

? ? ?在Linux程序中,fork()會(huì)產(chǎn)生一個(gè)和父進(jìn)程完全相同的子進(jìn)程,但子進(jìn)程在此后多會(huì)exec系統(tǒng)調(diào)用,出于效率考慮,linux中引入了“寫(xiě)時(shí)復(fù)制“技術(shù),也就是只有進(jìn)程空間的各段的內(nèi)容要發(fā)生變化時(shí),才會(huì)將父進(jìn)程的內(nèi)容復(fù)制一份給子進(jìn)程。

????? 那么子進(jìn)程的物理空間沒(méi)有代碼,怎么去取指令執(zhí)行exec系統(tǒng)調(diào)用呢?

????? 在fork之后exec之前兩個(gè)進(jìn)程用的是相同的物理空間(內(nèi)存區(qū)),子進(jìn)程的代碼段、數(shù)據(jù)段、堆棧都是指向父進(jìn)程的物理空間,也就是說(shuō),兩者的虛擬空間不同,但其對(duì)應(yīng)的物理空間是同一個(gè)。當(dāng)父子進(jìn)程中有更改相應(yīng)段的行為發(fā)生時(shí),再為子進(jìn)程相應(yīng)的段分配物理空間,如果不是因?yàn)閑xec,內(nèi)核會(huì)給子進(jìn)程的數(shù)據(jù)段、堆棧段分配相應(yīng)的物理空間(至此兩者有各自的進(jìn)程空間,互不影響),而代碼段繼續(xù)共享父進(jìn)程的物理空間(兩者的代碼完全相同)。而如果是因?yàn)閑xec,由于兩者執(zhí)行的代碼不同,子進(jìn)程的代碼段也會(huì)分配單獨(dú)的物理空間。??????

????? 在網(wǎng)上看到還有個(gè)細(xì)節(jié)問(wèn)題就是,fork之后內(nèi)核會(huì)通過(guò)將子進(jìn)程放在隊(duì)列的前面,以讓子進(jìn)程先執(zhí)行,以免父進(jìn)程執(zhí)行導(dǎo)致寫(xiě)時(shí)復(fù)制,而后子進(jìn)程執(zhí)行exec系統(tǒng)調(diào)用,因無(wú)意義的復(fù)制而造成效率的下降。

COW詳述:

???? 現(xiàn)在有一個(gè)父進(jìn)程P1,這是一個(gè)主體,那么它是有靈魂也就身體的。現(xiàn)在在其虛擬地址空間(有相應(yīng)的數(shù)據(jù)結(jié)構(gòu)表示)上有:正文段,數(shù)據(jù)段,堆,棧這四個(gè)部 分,相應(yīng)的,內(nèi)核要為這四個(gè)部分分配各自的物理塊。即:正文段塊,數(shù)據(jù)段塊,堆塊,棧塊。至于如何分配,這是內(nèi)核去做的事,在此不詳述。

1.????? 現(xiàn)在P1用fork()函數(shù)為進(jìn)程創(chuàng)建一個(gè)子進(jìn)程P2,

內(nèi)核:

(1)復(fù)制P1的正文段,數(shù)據(jù)段,堆,棧這四個(gè)部分,注意是其內(nèi)容相同。

(2)為這四個(gè)部分分配物理塊,P2的:正文段->PI的正文段的物理塊,其實(shí)就是不為P2分配正文段塊,讓P2的正文段指向P1的正文段塊,數(shù)據(jù)段->P2自己的數(shù)據(jù)段塊(為其分配對(duì)應(yīng)的塊),堆->P2自己的堆塊,棧->P2自己的棧塊。如下圖所示:同左到右大的方向箭頭表示復(fù)制內(nèi)容。

?

2.?????? 寫(xiě)時(shí)復(fù)制技術(shù):內(nèi)核只為新生成的子進(jìn)程創(chuàng)建虛擬空間結(jié)構(gòu),它們來(lái)復(fù)制于父進(jìn)程的虛擬究竟結(jié)構(gòu),但是不為這些段分配物理內(nèi)存,它們共享父進(jìn)程的物理空間,當(dāng)父子進(jìn)程中有更改相應(yīng)段的行為發(fā)生時(shí),再為子進(jìn)程相應(yīng)的段分配物理空間。

?

?

3.?????? vfork():這個(gè)做法更加火爆,內(nèi)核連子進(jìn)程的虛擬地址空間結(jié)構(gòu)也不創(chuàng)建了,直接共享了父進(jìn)程的虛擬空間,當(dāng)然了,這種做法就順?biāo)浦鄣墓蚕砹烁高M(jìn)程的物理空間

?

通過(guò)以上的分析,相信大家對(duì)進(jìn)程有個(gè)深入的認(rèn)識(shí),它是怎么一層層體現(xiàn)出自己來(lái)的,進(jìn)程是一個(gè)主體,那么它就有靈魂與身體,系統(tǒng)必須為實(shí)現(xiàn)它創(chuàng)建相應(yīng)的實(shí)體, 靈魂實(shí)體與物理實(shí)體。這兩者在系統(tǒng)中都有相應(yīng)的數(shù)據(jù)結(jié)構(gòu)表示,物理實(shí)體更是體現(xiàn)了它的物理意義。

???? 補(bǔ)充一點(diǎn):Linux COW與exec沒(méi)有必然聯(lián)系

參考資料

1.?Linux進(jìn)程管理——fork()和寫(xiě)時(shí)復(fù)制

總結(jié)

以上是生活随笔為你收集整理的fork、vfork、clone的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。