Copy-On-Write技術

來源:互聯網
上載者:User

linux核心在使用fork建立進程時,基本上會使用Copy-On-Write(COW)技術。這裡解釋一下COW技術以及為什麼在fork中使用。

WIKI上對COW的解釋:

Copy-on-write (sometimes referred to as "COW") is an optimization strategy used in computer programming. The fundamental idea is that if multiple callers ask for resources which are initially indistinguishable, they can all be given pointers to the same resource. This function can be maintained until a caller tries to modify its "copy" of the resource, at which point a true private copy is created to prevent the changes becoming visible to everyone else. All of this happens transparently to the callers. The primary advantage is that if a caller never makes any modifications, no private copy need ever be created.

意思上就是:在複製一個對象的時候並不是真正的把原先的對象複製到記憶體的另外一個位置上,而是在新對象的記憶體映射表中設定一個指標,指向來源物件的位置,並把那塊記憶體的Copy-On-Write位設定為1.

這樣,在對新的對象執行讀操作的時候,記憶體資料不發生任何變動,直接執行讀操作;而在對新的對象執行寫操作時,將真正的對象複製到新的記憶體位址中,並修改新對象的記憶體映射表指向這個新的位置,並在新的記憶體位置上執行寫操作。

這個技術需要跟虛擬記憶體和分頁同時使用,好處就是在執行複製操作時因為不是真正的記憶體複製,而只是建立了一個指標,因而大大提高效率。但這不是一直成立的,如果在複製新對象之後,大部分對象都還需要繼續進行寫操作會產生大量的分頁錯誤,得不償失。所以COW高效的情況只是在複製新對象之後,在一小部分的記憶體分頁上進行寫操作。

COW在編程中被廣泛應用。

特別是在作業系統當中,當一個程式運行結束時,作業系統並不會急著把其清除出記憶體,原因是有可能程式還會馬上再運行一次(從磁碟把程式裝入到記憶體是個很慢的過程),而只有當記憶體不夠用了,才會把這些還駐留記憶體的程式清出。

而對於Linux核心空間建立進程時的fork,由於在核心空間已經由代碼決定不使用COW技術(參見mm/memory.c Line 221)。從而由核心空間的進程0(main)建立進程1(init)不使用COW,系統對此次新進程建立進行了特殊處理(存在疑問,同樣是fork,如何?對這個fork的特殊處理,估計是schedule,看到再解決了)。進程0和進程1同時使用著核心代碼區內(<=1M)相同的代碼和資料記憶體頁面(640KB),只是執行代碼不在一處,因此他們也同時使用著相同的使用者堆棧區。在為進程1(init)複製其父進程(進程0)的頁目錄和頁表項時,進程0的640KB頁表項的屬性沒有改動過(仍然可讀寫),但是進程1的640KB對應的頁表項卻被設定成唯讀。因此當進程1(init)開始執行時,對使用者堆棧的入棧操作將導致頁面防寫保護異常,從而使得核心的記憶體管理程式為進程1在主記憶體區中分配一記憶體頁面,並把進程0中的頁面內容複寫到新的頁面上。從此時開始,進程1開始有自己獨立的記憶體頁面,由於此時的記憶體頁面在主記憶體區,因此進程1中繼續建立新的子進程時可以採用COW技術。

在Linux核心首先通過move_to_user_mode轉移到使用者模式下執行,至此main函數就以進程0的身份運行。而進程0是所有將建立進程的父進程,他建立進程1(init)時,fork的結果就是進程1與進程0擁有完全相同的記憶體空間、堆棧,這時進程0和進程1的記憶體還都在Linux核心空間中。

核心調度進程運行時次序是隨機的,有可能在進程0建立了進城1之後仍然允許進程0,由於兩個進程共用記憶體空間,為了不出現衝突問題,就必須要求進程0在進程1執行堆棧操作(進程1的堆棧操作會導致頁面保護異常,從而使得進程1在主記憶體區得到新的使用者頁面區,此時進程1和進程0才算是真正獨立,如前面所述)之前禁止使用使用者堆棧區。所以進程0在執行了fork(建立了進程1)之後的pause使用內嵌的方式,保證進程0(main)不會弄亂堆棧。

進程1中如果執行fork以及exec,此時的頁面空間已經到了主記憶體區,就可以使用COW了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.