使用windows記憶體 記憶體對映檔案

2021-07-09 06:56:55 字數 3143 閱讀 1303

和虛擬記憶體一樣,記憶體對映檔案可以用來保留乙個程序位址區域;但是,與虛擬記憶體不同,它提交的不是物理記憶體或是虛擬頁檔案,而是硬碟上的檔案。將檔案對映成記憶體,我們可以像使用內

存一樣使用檔案.

使用場合

它有三個主要用途:

系統載入exe和dll檔案

作業系統就是用它來載入exe和dll檔案建立程序,執行exe。這樣可以節省頁檔案和啟動時間。

訪問大資料檔案

如果檔案太大,比如超過了程序使用者區2g,用fopen是不能對檔案進行操作的。這時,可用記憶體對映檔案。對於大資料檔案可以不必對檔案執行i/o操作,不必對所有檔案內容進行快取。

程序共享機制

記憶體對映檔案是多個程序共享資料的一種較高效能的有效方式,它也是作業系統程序通訊機制的底層實現方法。rpc、com、ole、dde、視窗訊息、剪貼簿、管道、socket等都是使用記憶體對映檔案實現的。

作用:建立檔案核心物件api

其中,訪問屬性有:

0 不能讀寫 (用它可以訪問檔案屬性)

generic_read

generic_write

generic_read|generic_write;

共享模式:

0 獨享檔案,其他應用程式無法開啟

file_share_write

file_share_read|file_share_write

這個屬性依賴於訪問屬性,必須和訪問屬性不衝突。

當建立失敗時,返回invalid_handle_value。

作用:建立檔案對映核心物件

「檔案」是上面建立的控制代碼;

「安全屬性」是核心物件需要的,null表示使用系統預設的安全屬性;「保護屬性」是當將儲存器提交給程序空間時,需要的頁面屬性:page_readonly, page_readwrite和page_writecopy。這個屬性不能和檔案物件的訪問屬性衝突。除了這三個外,還有兩個屬性可以和它們連線使用(|)。當更新檔案內容時,不提供快取,直接寫入檔案,可用sec_nocache;當檔案是可執行檔案時,系統會根據節賦予不同的頁面屬性,可用sec_image。另外,sec_reserve和sec_commit用於稀疏提交的檔案對映,詳細介紹請參考下文。

「檔案大小高32位」和「檔案大小低32位」聯合起來告訴系統,這個對映所能支援的檔案大小(作業系統支援264b檔案大小);當這個值大於實際的檔案大小時,系統會擴大檔案到這個值,因為系統需要保證程序空間能完全被對映。值為0預設為檔案的大小,這時候如果檔案大小為0,建立失敗。

「對映名稱」是給使用者標識此核心物件,供各程序共享,如果為null,則不能共享。

物件建立失敗時返回null。

建立成功後,系統仍未為檔案保留程序空間。

作用:檔案對映核心物件對映到程序空間

「對映物件」是前面建立的物件;

「訪問屬性」可以是下面的值:file_map_write(讀和寫)、file_map_read、file_map_all_access(讀和寫)、file_map_copy。當使用file_map_copy時,系統分配虛擬頁檔案,當有寫操作時,系統會拷貝資料到這些頁面,並賦予page_readwrite屬性。

可以看到,每一步都需要設定這類屬性,是為了可以多點控制,試想,如果在這一步想有多種不同的屬性操作檔案的不同部分,就比較有用。

「偏移高32位」和「偏移低32位」聯合起來標識對映的開始位元組(位址是分配粒度的倍數);

「位元組數」指對映的位元組數,預設0為到檔案尾。

當你需要指定對映到**時,你可以使用:

pvoid mapviewoffile(handle 對映物件,dword訪問屬性,dword 偏移量高32位,dword 偏移量低32位,size_t 位元組數,pvoid 基位址)

「基位址」是對映到程序空間的首位址,必須是分配粒度的倍數。

作用:儲存檔案修改,

為了提高速度,更改檔案時可能只更改到了系統快取,這時,需要強制儲存更改到硬碟,特別是撤銷對映前。

「程序空間位址」指的是需要更改的第乙個位元組位址,系統會變成頁面的位址;

「位元組數」,系統會變成頁面大小的倍數。

寫入磁碟後,函式返回,對於網路硬碟,如果希望寫入網路硬碟後才返回的話,需要將file_flag_write_through引數傳給createfile。

當使用file_map_copy建立對映時,由於對資料的更改只是對虛擬頁檔案的修改而不是硬碟檔案的修改,當撤銷對映時,會丟失所做的修改。如果要儲存,怎麼辦?

你可以用file_map_write建立另外乙個對映,它對映到程序的另外一段空間;掃瞄第乙個對映的page_readwrite頁面(因為屬性被更改),如果頁面改變,用movememory或其他拷貝函式將頁面內容拷貝到第二次對映的空間裡,然後再呼叫flushviewoffile。當然,你要記錄哪個頁面被更改。

作用:撤銷對映,

pvbaseaddress 

這個位址必須與mapviewoffile返回值相同。

作用:關閉核心物件

在不需要核心物件時,盡早將其釋放,防止記憶體洩露。由於它們是核心物件,呼叫closehandle(handle)就可以了。

在mapviewoffile後馬上關閉記憶體對映控制代碼;

最後再撤銷對映。

對於大檔案,可以用多次對映的方法達到訪問的目的。有點像awe技術。

windows只保證同一檔案對映核心物件的多次對映的資料一致性,比如,當有兩次對映同一物件到二個程序空間時,乙個程序空間的資料改變後,另乙個程序空間的資料也會跟著改變;不保證不同對映核心物件的多次對映的一致性。所以,使用檔案對映時,最好在createfile時將共享模型設定為0獨享,當然,對於唯讀檔案沒這個必要。

2.5 解除安裝對映

bool unmapviewoffile(

lpcvoid lpbaseaddress //解除安裝的位址

);2.6 關閉記憶體對映檔案

closehandle

2.7 檔案關閉

closehandle

示例**:

#include "stdafx.h"

#include "windows.h"

void map( )

int main(int argc, char* argv)

windows記憶體對映

為了說明記憶體對映的使用方式,下面是個人寫的例子 首先建立了乙個大於2gb的檔案,並寫入一定量地測試資料,如下 然後讀取檔案中的資料測試,如下 最後採用記憶體對映的方式對這個大檔案中的字串翻轉,並讀取字串測試,如下 在記憶體對映時,採用多次mapviewoffile將大檔案分開多次對映到記憶體中,這...

windows中的記憶體對映

1.createfile 2.建立記憶體對映檔案 handle hfile,handle to file lpsecurity attributes lpattributes,security dword flprotect,protection dword dwmaximumsizehigh,hi...

使用記憶體檔案對映實現共享記憶體

不使用ipc中的共享記憶體 shm 使用記憶體檔案對映的方式來實現共享記憶體 共享記憶體寫入者 使用檔案記憶體對映進行記憶體共享 include include include include include include include include include include using...