2016-09-28 80 views
0

我正在閱讀有關使用COW - 在現代類UNIX系統中執行fork之後的方法。後叉工作後COW如何?

假設我們有進程--P1。它分叉;我們得到另一個進程 - P2。 由於COW,它們的虛擬內存由相同的物理頁面支持。 有一個頁面,其中一個靜態全局變量(例如,static long variable;以外的main)位於(在。數據段),其由物理頁A.備份

現在P1改變其靜態全局變量;內核在處理保護錯誤後,將新頁面(頁面B)映射到P1的虛擬內存以存儲該已更改的變量。

同樣的方法P2在處理保護錯誤後更改其靜態全局變量內核,將新頁面(頁面C)映射到P1的虛擬內存以存儲更改後的變量。

現在什麼都沒有引用頁面A. 它位於何處?我想這不是「懸在空中」,使一個物理頁面不能使用,從而浪費內存?

+0

爲什麼不只是修改A,因爲只有一個引用它?如果沒有使用它,爲什麼它會保存在物理內存中? –

+0

@Sami,你的意思是,P2可以改變A'頁面標誌而不是映射新的「C」頁面?我認爲父母可能有多個孩子,因此A應該保持只讀? –

回答

2

當頁面B被創建時,頁面A上的COW標誌被刪除,因爲該頁面不再被共享;在修改它之前不再需要複製它。因此,P2簡單地使用頁面A,可能根本不會導致頁面錯誤,當然也不需要複製頁面。因此,沒有頁面C並且頁面A沒有被忽略。

請注意,如果在修改頁面A上的變量之前,P1再次分叉,或者如果P2分叉,或者兩者兼有,則可能有3個或更多的引用頁面的進程。系統通常爲內存映射控制信息中的每個頁面維護一個引用計數器,記錄有多少進程將頁面映射到其進程內存中,並且該計數控制是否可以清除COW標誌。在引用該頁面之前只有一個進程,COW標誌保持有效。

exec操作將減少舊進程中所有頁面的引用計數,並且如果引用計數變爲零,則會釋放頁面以供重用。如果P1設置了一些明確共享的內存,即使參考計數器可能大於1,共享內存頁也不會設置COW標誌。

1

頁面A不會變成懸掛,因爲只有一個副本發生。

這兩個過程之一將首先觸發COW。它將得到新的框架B,而另一個過程用A粘住。

我們可以安排其他進程不發生頁面錯誤。這可能充滿了種族,特別是在SMP下,每個核心都有自己的TLB。

或者我們可以讓其他進程也出現頁面錯誤。它會知道幀A不再需要複製,因爲在跟蹤A的管理對象中存在引用計數,並且引用計數的值爲1,指示A是唯一映射的。因此,頁面錯誤處理程序會將頁面標記爲存在,並將其映射爲A.

如果父項產生子項,該子項退出,然後父項與先前共享的頁面進行了接觸,則會發生同樣的情況。由於它不再被共享,所以沒有理由複製它。

+0

如果進程快速生成多個子進程,會發生什麼情況?如果有任何孩子寫入頁面(因此導致保護錯誤並獲得新頁面),我們在內核中的某個地方得到了ref計數器? –

+1

@BulatM。它可以這樣工作。在某個時候,我們必須知道沒有其他人擁有該頁面,並且它可以留下。 – Kaz