1. 程式人生 > >寫時拷貝技術(copy-on-write)

寫時拷貝技術(copy-on-write)

 傳統的fork()系統呼叫直接把所有的資源複製給新建立的程序。這種實現過於簡單並且效率低下,因為它拷貝的資料也許並不共享,更糟的情況是,如果新程序打算立即執行一個新的映像,那麼所有的拷貝都將前功盡棄。Linux的fork()使用寫時拷貝(copy-on-write)頁實現。寫時拷貝是一種可以推遲甚至免除拷貝資料的技術。核心此時並不複製整個程序地址空間,而是讓父程序和子程序共享同一個拷貝。只有在需要寫入的時候,資料才會被複制,從而使各個程序擁有各自的拷貝。也就是說,資源的複製只有在需要寫入的時候才進行,在此之前,只是以只讀方式共享。這種技術使地址空間上的頁的拷貝被推遲到實際發生寫入的時候。在頁根本不會被寫入的情況下—舉例來說,fork()後立即呼叫exec()—它們就無需複製了。fork()的實際開銷就是複製父程序的頁表以及給子程序建立惟一的程序描述符。

在一般情況下,程序建立後都會馬上執行一個可執行的檔案,這種優化可以避免拷貝大量根本就不會被使用的資料(地址空間裡常常包含數十兆的資料)。由於Unix強調程序快速執行的能力,所以這個優化是很重要的。

實際上COW技術不僅僅在Linux程序上有應用,其他例如C++的String在有的IDE環境下也支援COW技術:

程式設計例項:

#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;

int main(int argc, char *argv[])
{
        string str1 = "hello world\n";
	string str2 = str1;

	printf("str1:%x  str2:%x\n", str1.c_str(), str2.c_str());
	str2.clear();
	str2 = "hello\n";
	printf("str1:%x  str2:%x\n", str1.c_str(), str2.c_str());
    return 0;
}
列印結果:

str1:9b59014  str2:9b59014
str1:9b59014  str2:9b5904c

這就說明:str1, str2一開始指向同一記憶體地址, 當str2內容改變後,則str2的地址發生改變,這有點像設計模式中單例懶惰模式,只有需要物件時才new物件。同理,只有寫入東西時才進行記憶體的再分配。