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í),才將父進(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ì)將子進(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的:正文段(為P1的正文段的物理塊,其實(shí)就是不為P2分配正文段塊,讓P2的正文段指向P1的正文段塊),數(shù)據(jù)段(P2自己的數(shù)據(jù)段塊,為其分配對(duì)應(yīng)的塊),堆(P2自己的堆塊),棧(P2自己的棧塊)。如下圖所示,同左到右大的方向箭頭表示復(fù)制內(nèi)容:

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

3. vfork
vfork的做法更加簡(jiǎn)單粗暴,內(nèi)核連子進(jìn)程的虛擬地址空間也不創(chuàng)建了,直接共享了父進(jìn)程的虛擬空間,當(dāng)然了,這種做法就順?biāo)浦鄣墓蚕砹烁高M(jìn)程的物理空間

總結(jié)
傳統(tǒng)的fork()系統(tǒng)調(diào)用直接把所有的資源復(fù)制給新創(chuàng)建的進(jìn)程。這種實(shí)現(xiàn)過(guò)于簡(jiǎn)單并且效率低下,因?yàn)樗截惖臄?shù)據(jù)也許并不共享,更糟的情況是,如果新進(jìn)程打算立即執(zhí)行一個(gè)新的映像,那么所有的拷貝將是無(wú)用功。
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í)候,數(shù)據(jù)才會(huì)復(fù)制,從而使各個(gè)進(jìn)程擁有各自的拷貝。也就是說(shuō),資源的復(fù)制只有在需要寫(xiě)入的時(shí)候才進(jìn)行,在此之前,只是以只讀方式共享。這種技術(shù)使地址空間的頁(yè)的拷貝被推遲到實(shí)際發(fā)生寫(xiě)入的時(shí)候。
在頁(yè)根本不會(huì)被寫(xiě)入的情況下,舉例來(lái)說(shuō),fork()之后立即調(diào)用exec(),它們就無(wú)需復(fù)制了,fork()的實(shí)際開(kāi)銷(xiāo)就是復(fù)制父進(jìn)程的頁(yè)表以及給子進(jìn)程創(chuàng)建唯一的進(jìn)程描述符。在一般情況下,進(jìn)程創(chuàng)建后都會(huì)馬上運(yùn)行一個(gè)可執(zhí)行的文件,這種優(yōu)化可以避免拷貝大量根本不會(huì)使用的數(shù)據(jù)(地址空間常常包含數(shù)十兆的數(shù)據(jù))。由于Unix強(qiáng)調(diào)進(jìn)程快速執(zhí)行的能力,所以這個(gè)優(yōu)化是很重要的,注:Linux COW和exec沒(méi)有必然聯(lián)系
以上這篇詳談Linux寫(xiě)時(shí)拷貝技術(shù)(copy-on-write)必看篇就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
您可能感興趣的文章:- linux采用scp命令拷貝文件到本地,拷貝本地文件到遠(yuǎn)程服務(wù)器的方法
- Linux使用scp命令進(jìn)行文件遠(yuǎn)程拷貝詳解
- Linux中拷貝 cp命令中拷貝所有的寫(xiě)法詳解
- Virtualbox主機(jī)和虛擬機(jī)之間文件夾共享及雙向拷貝(Windows->Windows, Windows->Linux)
- linux拷貝命令之高級(jí)拷貝scp命令詳解
- linux使用scp命令備份文件 scp拷貝文件
- 使用scp獲取遠(yuǎn)程linux服務(wù)器上的文件 linux遠(yuǎn)程拷貝文件
- linux下如何實(shí)現(xiàn)快速拷貝大文件