記憶體對映檔案(專門讀寫大檔案)zz

2021-05-24 01:37:54 字數 2553 閱讀 5150

引言

檔案操作是應用程式最為基本的功能之一,win32 api和mfc均提供有支援檔案處理的函式和類,常用的有win32 api的createfile()、writefile()、readfile()和mfc提供的cfile類等。一般來說,以上這些函式可以滿足大多數場合的要求,但是對於某些特殊應用領域所需要的動輒幾十gb、幾百gb、乃至幾tb的海量儲存,再以通常的檔案處理方法進行處理顯然是行不通的。目前,對於上述這種大檔案的操作一般是以記憶體對映檔案的方式來加以處理的,本文下面將針對這種windows核心程式設計技術展開討論。

記憶體對映檔案概述

記憶體檔案對映也是windows的一種記憶體管理方法,提供了乙個統一的記憶體管理特徵,使應用程式可以通過記憶體指針對磁碟上的檔案進行訪問,其過程就如同對載入了檔案的記憶體的訪問。通過檔案對映這種使磁碟檔案的全部或部分內容與程序虛擬位址空間的某個區域建立對映關聯的能力,可以直接對被對映的檔案進行訪問,而不必執行檔案i/o操作也無需對檔案內容進行緩衝處理。記憶體檔案對映的這種特性是非常適合於用來管理大尺寸檔案的。

在使用記憶體對映檔案進行i/o處理時,系統對資料的傳輸按頁面來進行。至於內部的所有記憶體頁面則是由虛擬記憶體管理器來負責管理,由其來決定記憶體頁面何時被分頁到磁碟,哪些頁面應該被釋放以便為其它程序提供空閒空間,以及每個程序可以擁有超出實際分配物理記憶體之外的多少個頁面空間等等。由於虛擬記憶體管理器是以一種統一的方式來處理所有磁碟i/o的(以頁面為單位對記憶體資料進行讀寫),因此這種優化使其有能力以足夠快的速度來處理記憶體操作。

使用記憶體對映檔案時所進行的任何實際i/o互動都是在記憶體中進行並以標準的記憶體位址形式來訪問。磁碟的週期性分頁也是由作業系統在後台隱蔽實現的,對應用程式而言是完全透明的。記憶體對映檔案的這種特性在進行大檔案的磁碟事務操作時將獲得很高的效益。

需要說明的是,在系統的正常的分頁操作過程中,記憶體對映檔案並非一成不變的,它將被定期更新。如果系統要使用的頁面目前正被某個記憶體對映檔案所占用,系統將釋放此頁面,如果頁面資料尚未儲存,系統將在釋放頁面之前自動完成頁面資料到磁碟的寫入。

對於使用頁虛擬儲存管理的windows作業系統,記憶體對映檔案是其內部已有的記憶體管理元件的乙個擴充。由可執行**頁面和資料頁面組成的應用程式可根據需要由作業系統來將這些頁面換進或換出記憶體。如果記憶體中的某個頁面不再需要,作業系統將撤消此頁面原擁用者對它的控制權,並釋放該頁面以供其它程序使用。只有在該頁面再次成為需求頁面時,才會從磁碟上的可執行檔案重新讀入記憶體。同樣地,當乙個程序初始化啟動時,記憶體的頁面將用來儲存該應用程式的靜態、動態資料,一旦對它們的操作被提交,這些頁面也將被備份至系統的頁面檔案,這與可執行檔案被用來備份執行**頁面的過程是很類似的。圖1展示了**頁面和資料頁面在磁碟儲存器上的備份過程:

圖1 程序的**頁、資料頁在磁碟儲存器上的備份

顯然,如果可以採取同一種方式來處理**和資料頁面,無疑將會提高程式的執行效率,而記憶體對映檔案的使用恰恰可以滿足此需求。

對大檔案的管理

記憶體對映檔案物件在關閉物件之前並沒有必要撤銷記憶體對映檔案的所有檢視。在物件被釋放之前,所有的髒頁面將自動寫入磁碟。通過 closehandle()關閉記憶體對映檔案物件,只是釋放該物件,如果記憶體對映檔案代表的是磁碟檔案,那麼還需要呼叫標準檔案i/o函式來將其關閉。在處理大檔案處理時,記憶體對映檔案將表示出卓越的優勢,只需要消耗極少的物理資源,對系統的影響微乎其微。下面先給出記憶體對映檔案的一般程式設計流程框圖:

圖2 使用記憶體對映檔案的一般流程

而在某些特殊行業,經常要面對十幾gb乃至幾十gb容量的巨型檔案,而乙個32位程序所擁有的虛擬位址空間只有232 = 4gb,顯然不能一次將檔案映像全部對映進來。對於這種情況只能依次將大檔案的各個部分對映到程序中的乙個較小的位址空間。這需要對上面的一般流程進行適當的更改:

1)對映檔案開頭的映像。

2)對該映像進行訪問。

3)取消此映像

4)對映乙個從檔案中的乙個更深的位移開始的新映像。

5)重複步驟2,直到訪問完全部的檔案資料。

下面給出一段根據此描述而寫出的對大於4gb的檔案的處理**:

區保護屬性

說明sec_commit

為區中的所有頁面在記憶體中或磁碟頁面檔案中分配物理儲存器

sec_image

告知系統,對映的檔案是乙個可移植的exe檔案映像

sec_nocache

告知系統,未將檔案的任何記憶體對映檔案放入快取記憶體,多供硬體裝置驅動程式開發人員使用

sec_reserve

對乙個區的所有頁面進行保留而不分配物理儲存器

本文對記憶體對映檔案在大檔案處理中的應用作了較為詳細的闡述。經實際測試,記憶體對映檔案在處理大資料量檔案時表現出了良好的效能,比通常使用 cfile類和readfile()和writefile()等函式的檔案處理方式具有明顯的優勢。本文所述程式**在windows 2000 professional下由microsoft visual c++ 6.0編譯通過

大檔案處理 記憶體檔案對映

記憶體對映檔案,是由乙個檔案到一塊記憶體的對映。與虛擬記憶體有些類似,通過記憶體對映檔案可以保留乙個位址空間的區域,同時將物理儲存器提交給此區域,記憶體檔案對映的物理儲存器來自乙個已經存在的磁碟上的檔案,而且在對該檔案進行操作之前必須首先對檔案進行對映。另外,記憶體對映檔案是由乙個檔案到程序位址空間...

記憶體對映檔案機制處理大檔案

原文 hongchangfirst hongchangfirst的主頁 先說結論 使用記憶體對映檔案來處理大檔案可以提高效率。為什麼呢?我們先來看看如果不使用記憶體對映檔案的處理流程是怎樣的,首先我們得先讀出磁碟檔案的內容到記憶體中,然後修改,最後回寫到磁碟上。第一步讀磁碟檔案是要經過一次系統呼叫的...

iOS將大檔案對映到記憶體 讀取大檔案

from 2012年10月23日 在 中國區gps偏移糾正 適用於google地圖 一文中曾讀取乙個78m的大資料檔案,一開始採用了nsdata的datawithcontentsoffile 方法。不少人反饋說如果直接使用,將會耗盡ios的記憶體。其實這個是可以改善的。nsdata還有乙個api i...