Linux內核學習---寫時複製(COW)技術

Linux內核學習—寫時複製(COW)技術

寫時複製技術(copy-on-write)

傳統的Unix系統以一種比較統一的方式對待所有的進程:子進程複製父進程所有的資源。這種方法有一些很明顯弊端:

  • 將使用大量內存
  • 複製操作耗費大量時間
  • 通常情況下子進程不需要讀或者寫父進程擁有的所有資源,故該方法效率也是非常低的(複製的大量資源都沒有使用)

並且,如果應用程序在進程複製後使用exec立即加載新程序,這意味着之前的複製基本是完全多餘的,因爲進程地址空間需要重新初始化,之前複製的數據不再需要,這導致之前做的都是無用功。

因此,現代Unix內核採用了寫時複製(copy-on-write)機制避免fork時將父進程所有資源都複製到子進程。

該技術的核心思想是:只有在不得不復制內容時纔去複製內容(tips:感覺操作系統中很多技術都是用到了該思想,如果一個操作的消耗比較大,那麼就應該儘可能晚一點少一點該操作。例如:識別dirty bit的 extended clock頁替換算法,還有很多操作系統在換頁機制上均採用的是lazy換頁,也就是不得不換頁才換)

具體操作:當fork時只複製頁表,因此fork之後父子進程的地址空間指向的是相同的物理內存頁。如果父子進程都不需要修改彼此的頁(也就是隻讀),則共享即可滿足,因此將對應的頁都標記爲只讀訪問。只有兩者中有一個進程要進行修改相應的物理頁(也就是寫操作),則會引發頁錯誤。內核檢測該頁錯誤是否是因爲對只讀頁面進行寫操作引發的,如果是的話則處理該異常:拷貝該頁面的內容到一個新的物理頁,並設置其爲可寫,將新的物理頁分配給正在寫的進程,即修改該進程的頁表中對應的這一頁,重新執行寫操作。

當一個用戶父進程創建自己的子進程時,父進程會把其申請的用戶空間設置爲只讀,子進程可共享父進程佔用的用戶內存空間中的頁面(這就是一個共享的資源)。當其中任何一個進程修改此用戶內存空間中的某頁面時,內核會通過page fault異常獲知該操作,並完成拷貝內存頁面,使得兩個進程都有各自的內存頁面。這樣一個進程所做的修改不會被另外一個進程可見了。

通過COW機制,使得內核可以儘可能地延遲內存頁的訪問,最重要的是,由於很多情況下並不需要寫操作或只需要很少量的寫操作,因此該機制將節省大量時間,提高效率。

實際上,Linux實現該機制時,對每個頁描述符增添一個跟蹤共享相應頁框的進程數目的字段_count。

主要思路:首先判斷缺頁異常是否是因爲訪問內存中一個現有的頁引起的,然後獲取該頁相應的頁框描述符,只要判斷該複製是否是有必要的(如果只有一個進程擁有這個頁,就不需要複製,只需要將改頁改爲可寫即可。如果有多個進程訪問該頁,則需要複製),如果需要複製則拷貝該頁後修改要寫進程的頁表項。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章