C 寫時拷貝實現原理及例項解析

2022-10-06 02:57:07 字數 1874 閱讀 2568

一、什麼是寫時拷貝

寫入時複製是一種計算機程式設計領域的優化策略。其核心思想是,如果有多個呼叫者同時請求相同資源(如記憶體或磁碟上的資料儲存),他們會共同獲取相同的指標指向相同的資源,直到某個呼叫者試圖修改資源的內容時,系統才會真正複製乙份專用副本(private copy)給該呼叫者,而其他呼叫者所見到的最初的資源仍然保持不變。

這個過程對其他的呼叫者是透明的(transparently)。

此作法的主要優點是如果呼叫者沒有修改該資源,就不會有副本被建立,因此多個呼叫者只是讀取操作是可以共享同乙份資源。

寫時拷貝技術是一種很重要的優化手段,核心是懶惰處理實體資源請求,在多個實體資源之間只是共享資源,起初是並不真正實現資源拷程式設計客棧貝,

只有當實體有需要對資源進行修改時才真正為實體分配私有資源。但寫時拷貝技術技術也有它的優點和缺點:

1、寫時拷貝技術可以減少分配和複製大量資源時帶來的瞬間延時,但實際上是將這種延時附加到了後續的操作之中。

2、寫時拷貝技術可以減少不必要的資源分配。比如fork程序時,並不是所有的頁面都需要複製,父程序的**段和唯讀資料段都不被允許修改,所以無需複製。

二、寫時拷貝技術的應用

1、虛擬記憶體管理中的寫時複製

一般把這種被共享訪問的頁面標記為唯讀。當乙個task試圖向記憶體中寫入資料時,記憶體管理單元(mmu)丟擲乙個異常,核心處理該異常時為該task分配乙份物理記憶體並複製資料到此記憶體,

重新向mmu發出執行該task的寫操作。

比如linux的fork()使用寫時拷貝頁來實現新程序的建立,它是一種可推遲甚至避免資料拷貝的技術,開始時核心並不會複製整個位址空間,而是讓父子程序共享位址空間,只有在寫時才複製位址空間,使得父子程序都擁有獨立的位址空間,即資源的複製是在只有需要寫入時才會發生。在此之前都是以讀的方式去和父程序共享資源,這樣,在頁根本不會被寫入的場景下,fork()立即執行exec(),無需對位址空間進行複製,fork()的實際開銷就是複製父程序的乙個頁表和為子程序建立乙個程序描述符,也就是說只有當程序空間中各段的記憶體內容發生變化時,父程序才將其內容複製乙份傳給子程序,大大提高了效率。

2、資料儲存中的寫時複製

linux等的檔案管理系統使用了寫時複製策略。

舉個例子,比如我們有個程式要寫檔案,不斷地根據網路傳來的資料寫,如果每一次fwrite或是fprintf都要進行乙個磁碟的i/o操作的話,都簡直就是效能上巨大的損失,

因此通常的做法是,每次寫檔案操作都寫在特定大小的一塊記憶體中(磁碟快取),只有當我們關閉檔案時,才寫到磁碟上(這就是為什麼如果檔案不關閉,所寫的東西會丟失的原因)

3、軟體應用中的寫時複製

在我們經常使用的stl標準模板庫中的string類,也是乙個具有寫時才拷貝技術的類。為了提高效能,stl中的許多類都採www.cppcns.com用了寫時拷貝技術。但是在c++11標準中為了提高並行性取消了這一策略

class string

//析構函式

~string()

}//拷貝構造(共享記憶體)

string(string& str)

}//對符進行過載,對字串進行操作的時候,開始寫時複製

char& operator(unsigned int idx)

//引用計數減一

_ptr[_len + 1]--;

char* tmp = new char[_len + 1 + 1];

strncpy(tmp, _ptr, _len + 1);程式設計客棧

_ptr = tmp;

// 設定新的共享記憶體的引用計數

_ptr[_len + 1] = 0;

return _ptr[idx];

}private:

int _len;

char* _ptr;

};本文標題: c++寫時拷貝實現原理及例項解析

本文位址:

c 深淺拷貝 寫時拷貝實現

淺拷貝 在拷貝構造的時候,直接將原內容的位址交給要拷貝的類,兩個類共同指向一片空間。但是存在很大的缺陷 一旦對s2進行操作,s1的內容也會改變 析構時先析構s2,再析構s1,但是由於s1,s2指向同一片空間,會導致一片空間的二次析構導致出錯。深拷貝 通過開闢和源空間大小相同的空間並將內容拷貝下來再進...

c 寫時拷貝

在c 中乙個類有六個預設成員函式,其中拷貝建構函式分為淺拷貝和深拷貝 淺拷貝是一種值拷貝,深拷貝不僅是值拷貝,還要做其他處理 深淺拷貝的區別 由上圖可知當乙個拷貝構造乙個需動態開闢空間的物件時,用淺拷貝時會出現同一塊空間被釋放兩次,這樣顯然有問題,用深拷貝的話可以解決此問題,但當拷貝構造出來的物件,...

c 寫時拷貝1

class string string const string s ptr new char strlen s.ptr 1 另外開闢空間 string private char ptr void test int end gettickcount 記錄此時毫秒數 string const stri...