【轉】Copy-On-Write技術 [ linux fork程序時使用技術]
inux核心在使用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
意思上就是:在複製一個物件的時候並不是真正的把原先的物件複製到記憶體的另外一個位置上,而是在新物件的記憶體對映表中設定一個指標,指向源物件的位置,並把那塊記憶體的Copy-On-Write位設定為1.
這樣,在對新的物件執行讀操作的時候,記憶體資料不發生任何變動,直接執行讀操作;而在對新的物件執行寫操作時,將真正的物件複製到新的記憶體地址中,並修改新物件的記憶體對映表指向這個新的位置,並在新的記憶體位置上執行寫操作。
這個技術需要跟虛擬記憶體和分頁同時使用,好處就是在執行復制操作時因為不是真正的記憶體複製,而只是建立了一個指標,因而大大提高效率。但這不是一直成立的,如果在複製新物件之後,大部分物件都還需要繼續進行寫操作會產生大量的分頁錯誤,得不償失。所以COW高效的情況只是在複製新物件之後,在一小部分的記憶體分頁上進行寫操作。
COW在程式設計中被廣泛應用。
特別是在作業系統當中,當一個程式執行結束時,作業系統並不會急著把其清除出記憶體,原因是有可能程式還會馬上再執行一次(從磁碟把程式裝入到記憶體是個很慢的過程),而只有當記憶體不夠用了,才會把這些還駐留記憶體的程式清出。
而對於Linux核心空間建立程序時的fork,由於在核心空間已經由程式碼決定不使用COW技術(參見mm/memory.c Line 221)。從而由核心空間
在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了。