1. 程式人生 > >CreateFileMapping MapViewOfFile UnmapViewOfFile函數用法及示例

CreateFileMapping MapViewOfFile UnmapViewOfFile函數用法及示例

大文件 讀寫 進程 管理機 初級 htm box void 訪問共享


內存映射API函數CreateFileMapping創建一個有名的共享內存:
HANDLE CreateFileMapping(
HANDLE hFile, // 映射文件的句柄,
//設為0xFFFFFFFF以創建一個進程間共享的對象
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 安全屬性
DWORD flProtect, // 保護方式
DWORD dwMaximumSizeHigh, //對象的大小
DWORD dwMaximumSizeLow,
LPCTSTR lpName // 必須為映射文件命名
);

與虛擬內存類似,保護方式可以是PAGE_READONLY或是PAGE_READWRITE。如果多進程都對同一共享內存進行寫訪問,則必須保持相互間同步。映射文件還可以指定PAGE_WRITECOPY標誌,可以保證其原始數據不會遭到破壞,同時允許其他進程在必要時自由的操作數據的拷貝。

在創建文件映射對象後使用可以調用MapViewOfFile函數映射到本進程的地址空間內。

下面說明創建一個名為MySharedMem的長度為4096字節的有名映射文件:
HANDLE hMySharedMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF),
NULL,PAGE_READWRITE,0,0x1000,"MySharedMem");
並映射緩存區視圖:
LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile,
FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);

其他進程訪問共享對象,需要獲得對象名並調用OpenFileMapping函數。
HANDLE hMySharedMapFile=OpenFileMapping(FILE_MAP_WRITE,
FALSE,"MySharedMem");

一旦其他進程獲得映射對象的句柄,可以象創建進程那樣調用MapViewOfFile函數來映射對象視圖。用戶可以使用該對象視圖來進行數據讀寫操作,以達到數據通訊的目的。

當用戶進程結束使用共享內存後,調用UnmapViewOfFile函數以取消其地址空間內的視圖:
if (!UnmapViewOfFile(pszMySharedMapView))
{

AfxMessageBox("could not unmap view of file");

}

以下是一個示例程序:

void CreateFileMappingEx()
{
DWORD timebegin = ::timeGetTime();
HANDLE fp = CreateFile(TEXT("E://jyzhj2.rar"),//這裏輸入需要復制的文件 src
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);

if(fp == NULL)
{
cout<<"錯誤"<<endl;
return;
}

DWORD dwBytesInBlock = GetFileSize(fp,NULL); //文件長度

// 創建文件映射內核對象,句柄保存於hFileMapping
HANDLE hFileMapping = CreateFileMapping(fp,
NULL,
PAGE_READWRITE,
0,//(DWORD)(dwBytesInBlock >> 16),
dwBytesInBlock,//(DWORD)(dwBytesInBlock & 0x0000FFFF),
NULL);

int dwError = GetLastError();

// 釋放文件內核對象
CloseHandle(fp);

// 偏移地址
__int64 qwFileOffset = 0;

// 將文件數據映射到進程的地址空間
LPVOID pbFile = (LPVOID)MapViewOfFile( hFileMapping,
FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset >> 32),
(DWORD)(qwFileOffset & 0xFFFFFFFF),
dwBytesInBlock);

HANDLE wp = CreateFile( TEXT("E://仙劍5.rar"),//這裏輸入 需要粘貼的文件 dst
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_WRITE_THROUGH,
NULL);

HANDLE hFileMapping2 = CreateFileMapping( wp,
NULL,
PAGE_READWRITE,
0,//(DWORD)(dwBytesInBlock >> 16),
dwBytesInBlock,//(DWORD)(dwBytesInBlock & 0x0000FFFF),
NULL);


CloseHandle(wp);

LPVOID pbFile2 = (LPVOID)MapViewOfFile( hFileMapping2,
FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset >> 32),
(DWORD)(qwFileOffset & 0xFFFFFFFF),
dwBytesInBlock);

memcpy(pbFile2,pbFile,dwBytesInBlock);

UnmapViewOfFile(pbFile2);
UnmapViewOfFile(pbFile);

CloseHandle(hFileMapping2);
CloseHandle(hFileMapping);
DWORD timeend = ::timeGetTime();
cout<<"CreateFileMapping和MapViewOfFile程序運行時間為"<<timeend - timebegin<<endl;
}
測試創建和打開文件映射的時候老是得到"句柄無效"的錯誤, 仔細看了MSDN以後才發覺是函數認識不透, 這裏把相關的解釋翻譯出來

HANDLE CreateFileMapping(
HANDLE hFile, //物理文件句柄
LPSECURITY_ATTRIBUTES lpAttributes, //安全設置
DWORD flProtect, //保護設置
DWORD dwMaximumSizeHigh, //高位文件大小
DWORD dwMaximumSizeLow, //低位文件大小
LPCTSTR lpName //共享內存名稱
);

1) 物理文件句柄
任何可以獲得的物理文件句柄, 如果你需要創建一個物理文件無關的內存映射也無妨, 將它設置成為 0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了.

如果需要和物理文件關聯, 要確保你的物理文件創建的時候的訪問模式和"保護設置"匹配, 比如: 物理文件只讀, 內存映射需要讀寫就會發生錯誤. 推薦你的物理文件使用獨占方式創建.

如果使用 INVALID_HANDLE_VALUE, 也需要設置需要申請的內存空間的大小, 無論物理文件句柄參數是否有效, 這樣 CreateFileMapping 就可以創建一個和物理文件大小無關的內存空間給你, 甚至超過實際文件大小, 如果你的物理文件有效, 而大小參數為0, 則返回給你的是一個和物理文件大小一樣的內存空間地址範圍. 返回給你的文件映射地址空間是可以通過復制, 集成或者命名得到, 初始內容為0.

2) 保護設置
就是安全設置, 不過一般設置NULL就可以了, 使用默認的安全配置. 在win2k下如果需要進行限制, 這是針對那些將內存文件映射共享給整個網絡上面的應用進程使用是, 可以考慮進行限制.

3) 高位文件大小
弟兄們, 我想目前我們的機器都是32位的東東, 不可能得到超過32位進程所能尋址的私有32位地址空間, 一般還是設置0吧, 我沒有也不想嘗試將它設置超過0的情況.
4) 低位文件大小
這個還是可以進行設置的, 不過為了讓其他共享用戶知道你申請的文件映射的相關信息, 我使用的時候是在獲得的地址空間頭部添加一個結構化描述信息, 記錄內存映射的大小, 名稱等, 這樣實際申請的空間就比輸入的增加了一個頭信息結構大小了, 我認為這樣類似BSTR的方式應該是比較合理的.

5) 共享內存名稱
這個就是我今天測試的時候碰壁的禍根, 因為為了對於內存進行互斥訪問, 我設置了一個互斥句柄, 而名稱我選擇和命名共享內存同名, 之下就是因為他們使用共同的namespace導致了錯誤, 呵呵.

7) 調用CreateFileMapping的時候GetLastError的對應錯誤
ERROR_FILE_INVALID 如果企圖創建一個零長度的文件映射, 應有此報
ERROR_INVALID_HANDLE 如果發現你的命名內存空間和現有的內存映射, 互斥量, 信號量, 臨界區同名就麻煩了
ERROR_ALREADY_EXISTS 表示內存空間命名已經存在

8) 相關服務或者平臺的命名保留
Terminal Services:
命名可以包含 "Global/" 或者 "Local/" 前綴在全局或者會話名空間初級文件映射. 其他部分可以包含任何除了(/)以外的字符, 可以參考 Kernel Object Name Spaces.

Windows 2000 or later:
如果 Terminal Services 沒有運行 "Global/" 和 "Local/" 前綴的特殊含義就被忽略了

創建文件視圖

要將文件中的數據映射到進程的虛擬內存中,你必須創建一個文件的視圖。
MapViewOfFile和MapViewOfFileEx函數使用CreateFileMapping返回的文件映射對象句柄來在進程的虛擬地址空間裏建立文件的視圖,或者文件的某個部分。如果這些函數指定的權限標誌和CreateFileMapping中的權限標誌不一致,則會執行失敗。
MapViewOfFile函數返回一個指向文件視圖的指針。利用MapViewOfFile中聲明的地址指針,程序就可以從文件中讀以及向文件中寫入數據。向文件視圖中寫入數據會導致文件映射對象改變。真正將數據寫入到磁盤上的文件,由系統負責處理。數據並不是馬上就別寫到磁盤上,很多文件的輸入輸出都被緩存起來,以改善系統的性能。程序可以調用FlushViewOfFile函數來越過這個方式,強迫系統馬上將數據寫入到磁盤中去。
MapViewOfFileEx函數和MapViewOfFile函數作的工作是一模一樣的,只不過可以利用MapViewOfFileEx函數的lpvBase參數,來指定文件視圖在進程虛擬地址空間中的基礎地址。如果在指定的地址處沒有足夠的空間,則調用失敗。
1、lpvBase參數必須是系統內存最小單位的整數倍,否則調用會失敗。要得到系統內存的最小單位,使用GetSystemInfo函數,他將信息寫到SYSTEM_INFO結構的成員中。
程序可以從同一個文件映射對象中創建多個文件視圖。文件視圖可以是不同的大小,但他們必須小於文件映射對象。MapViewOfFile函數的dwOffsetHigh和dwOffsetLow參數必須是系統內存最小單位的整數倍。


文件映射問題
內存映射文件並不是簡單的文件I/O操作,實際用到了Windows的核心編程技術--內存管理。所以,如果想對內存映射文件有更深刻的認識,必須對Windows操作系統的內存管理機制有清楚的認識,內存管理的相關知識非常復雜,超出了本文的討論範疇,在此就不再贅述,感興趣的讀者可以參閱其他相關書籍。下面給出使用內存映射文件的一般方法:

  首先要通過CreateFile()函數來創建或打開一個文件內核對象,這個對象標識了磁盤上將要用作內存映射文件的文件。在用CreateFile()將文件映像在物理存儲器的位置通告給操作系統後,只指定了映像文件的路徑,映像的長度還沒有指定。為了指定文件映射對象需要多大的物理存儲空間還需要通過CreateFileMapping()函數來創建一個文件映射內核對象以告訴系統文件的尺寸以及訪問文件的方式。在創建了文件映射對象後,還必須為文件數據保留一個地址空間區域,並把文件數據作為映射到該區域的物理存儲器進行提交。由MapViewOfFile()函數負責通過系統的管理而將文件映射對象的全部或部分映射到進程地址空間。此時,對內存映射文件的使用和處理同通常加載到內存中的文件數據的處理方式基本一樣,在完成了對內存映射文件的使用時,還要通過一系列的操作完成對其的清除和使用過資源的釋放。這部分相對比較簡單,可以通過UnmapViewOfFile()完成從進程的地址空間撤消文件數據的映像、通過CloseHandle()關閉前面創建的文件映射對象和文件對象。

內存映射文件相關函數

  在使用內存映射文件時,所使用的API函數主要就是前面提到過的那幾個函數,下面分別對其進行介紹:

HANDLE CreateFile(LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);

  函數CreateFile()即使是在普通的文件操作時也經常用來創建、打開文件,在處理內存映射文件時,該函數來創建/打開一個文件內核對象,並將其句柄返回,在調用該函數時需要根據是否需要數據讀寫和文件的共享方式來設置參數dwDesiredAccess和dwShareMode,錯誤的參數設置將會導致相應操作時的失敗。

HANDLE CreateFileMapping(HANDLE hFile,
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName);

  CreateFileMapping()函數創建一個文件映射內核對象,通過參數hFile指定待映射到進程地址空間的文件句柄(該句柄由CreateFile()函數的返回值獲取)。由於內存映射文件的物理存儲器實際是存儲於磁盤上的一個文件,而不是從系統的頁文件中分配的內存,所以系統不會主動為其保留地址空間區域,也不會自動將文件的存儲空間映射到該區域,為了讓系統能夠確定對頁面采取何種保護屬性,需要通過參數flProtect來設定,保護屬性PAGE_READONLY、PAGE_READWRITE和PAGE_WRITECOPY分別表示文件映射對象被映射後,可以讀取、讀寫文件數據。在使用PAGE_READONLY時,必須確保CreateFile()采用的是GENERIC_READ參數;PAGE_READWRITE則要求CreateFile()采用的是GENERIC_READ|GENERIC_WRITE參數;至於屬性PAGE_WRITECOPY則只需要確保CreateFile()采用了GENERIC_READ和GENERIC_WRITE其中之一即可。DWORD型的參數dwMaximumSizeHigh和dwMaximumSizeLow也是相當重要的,指定了文件的最大字節數,由於這兩個參數共64位,因此所支持的最大文件長度為16EB,幾乎可以滿足任何大數據量文件處理場合的要求。

LPVOID MapViewOfFile(HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberOfBytesToMap);

  MapViewOfFile()函數負責把文件數據映射到進程的地址空間,參數hFileMappingObject為CreateFileMapping()返回的文件映像對象句柄。參數dwDesiredAccess則再次指定了對文件數據的訪問方式,而且同樣要與CreateFileMapping()函數所設置的保護屬性相匹配。雖然這裏一再對保護屬性進行重復設置看似多余,但卻可以使應用程序能更多的對數據的保護屬性實行有效控制。MapViewOfFile()函數允許全部或部分映射文件,在映射時,需要指定數據文件的偏移地址以及待映射的長度。其中,文件的偏移地址由DWORD型的參數dwFileOffsetHigh和dwFileOffsetLow組成的64位值來指定,而且必須是操作系統的分配粒度的整數倍,對於Windows操作系統,分配粒度固定為64KB。當然,也可以通過如下代碼來動態獲取當前操作系統的分配粒度:

SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;

  參數dwNumberOfBytesToMap指定了數據文件的映射長度,這裏需要特別指出的是,對於Windows 9x操作系統,如果MapViewOfFile()無法找到足夠大的區域來存放整個文件映射對象,將返回空值(NULL);但是在Windows 2000下,MapViewOfFile()只需要為必要的視圖找到足夠大的一個區域即可,而無須考慮整個文件映射對象的大小。

  在完成對映射到進程地址空間區域的文件處理後,需要通過函數UnmapViewOfFile()完成對文件數據映像的釋放,該函數原型聲明如下:

BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);

  唯一的參數lpBaseAddress指定了返回區域的基地址,必須將其設定為MapViewOfFile()的返回值。在使用了函數MapViewOfFile()之後,必須要有對應的UnmapViewOfFile()調用,否則在進程終止之前,保留的區域將無法釋放。除此之外,前面還曾由CreateFile()和CreateFileMapping()函數創建過文件內核對象和文件映射內核對象,在進程終止之前有必要通過CloseHandle()將其釋放,否則將會出現資源泄漏的問題。

  除了前面這些必須的API函數之外,在使用內存映射文件時還要根據情況來選用其他一些輔助函數。例如,在使用內存映射文件時,為了提高速度,系統將文件的數據頁面進行高速緩存,而且在處理文件映射視圖時不立即更新文件的磁盤映像。為解決這個問題可以考慮使用FlushViewOfFile()函數,該函數強制系統將修改過的數據部分或全部重新寫入磁盤映像,從而可以確保所有的數據更新能及時保存到磁盤。

共享內存對象方法(MapViewOfFile)
共享內存對象方法通常,將頁面文件支持的內存映射文件作為在用戶進程之間共享內存的技術。但是,可以使用相同的技術在用戶進程與設備驅動程序之間共享內存。使用這種技術有兩種方法。

第一種方法中,通過使用 OpenFileMapping,然後調用 MapViewOfFile 函數以獲取指向某個區域或所有共享內存的指針,驅動程序可以創建命名內存對象(稱為“區域對象”),並且一個或多個用戶應用程序可以打開相同的對象。通過向區域對象指定保護屬性,可以定義進程操縱內存的方式。

第二種方法中,應用程序可以用 CreateFileMapping 在用戶模式下創建命名內存對象。驅動程序通過使用 ZwOpenSection 並調用 ZwMapViewOfSection 獲取指向它的指針,可以打開相同的內存對象。始終用異常處理程序在內核模式下訪問此內存地址。

由於該對象始終映射在進程的用戶地址空間(小於 0x80000000,無論對象是在內核模式還是在用戶模式中創建的)中,因此只在進程上下文中訪問地址時,地址才有效。每次在相同內存對象上調用 MapViewOfFile 或 ZwMapViewOfSection 時,都將返回不同的內存地址(即使是相同的進程,也是如此)。建議不要使用這種方法(尤其是低級設備驅動程序),正如前面所述,這是因為地址範圍限定於進行對象映射的進程,並且不能在 DPC 或 ISR 中對地址進行訪問。另外,在 DDK 中沒有記載在內核模式下創建內存對象的 API。

但是,要在提高的 IRQL(如 DPC 或 ISR 中)上使用該地址,必須查明並鎖定緩沖區頁面,並獲取系統虛擬地址 MmGetSystemAddressForMdl(正如本文前面 IOCTL 方法中所述)。

僅當要在兩個(或更多)用戶進程與一個(或多個)設備驅動程序之間共享內存的情況下,這種方法才比較簡便。否則,使用 IOCTL 技術在用戶進程與設備驅動程序之間共享內存更加簡單高效。

內存映射文件技術
1. 用途和基本操作
用於不同進程之間的內存共享操作, 可以將一個物理文件映射到內存當中然後直接利用分配到的或者打開的命名共享內存的地址空間實現資源共享訪問

2. 相關流程
1) 新建命名共享內存
首先利用CreateFile或者CreateFileForMapping獲得一個用於映射的物理文件句柄, 然後利用該文件句柄結合CreateFileMapping得到一個命名的共享內存映射文件句柄。
//CreateFileMapping 為指定文件創建一個有名或無名的文件映象;
HANDLE CreateFileMapping(
HANDLE hFile, // 映射文件的句柄
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 安全描述符指針
DWORD flProtect, // 對映射對象的保護
DWORD dwMaximumSizeHigh, // 對象最大長度的高32位
DWORD dwMaximumSizeLow, // 對象最大長度的低32位
LPCTSTR lpName // 文件內存映射對象的名字
);

註意:
hFile:映射文件的句柄,文件的打開模式必須與flProtect參數指定的相一致;如果這個參數值為0xFFFFFFFF,那麽必須在dwMaximumSizeHigh和dwMaximumSizeLow參數中指定映射對象的大小。並且將在操作系統虛擬內存頁面替換文件中創建文件映射對象,而不是使用磁盤文件,同時必須給出這個映射對象的大小。文件映射對象通過副本,遺傳或名字來共享。
lpFileMappingAttributes:安全描述符指針,決定返回句柄是否能被子進程繼承,如果是NULL,那麽子進程不能繼承。WinNt中,如果是NULL,那麽文件映射對象得到一個默認的安全描述符。
flProtect:為得到的文件試圖指定保護模式,可以被設置為下列值:
PAGE_READONLY :只讀屬性,並且hFile對應的文件必須以GENERIC_READ形式打開。
PAGE_READWRITE:可讀可寫屬性,並且hFile對應的文件必須以GENERIC_READ 和 GENERIC_WRITE形式打開。
PAGE_WRITECOPY:對可寫區域復制後操作,並且hFile對應的文件必須以GENERIC_READ 和 GENERIC_WRITE形式打開。
dwMaximumSizeHigh,dwMaximumSizeLow:如果這兩個參數為0,則文件映射對象的最大長度等於hFile指定的文件長度。
lpName:文件映射對象的名字,如果這個名字已存在,則按照flProtect指定的來處理映射對象。如果此參數為空,則創建一個無名字的文件映射對象。如果此參數的名字與系統事件的名字相同,則函數執行失敗,GetLastError返回 ERROR_INVALID_HANDLE;

返回值:函數調用成功返回文件映射對象的句柄,如果文件映射對象已經存在則返回原有映射對象的句柄,GetLastError返回ERROR_ALREADY_EXISTS。函數執行失敗返回Null。

2) 打開命名共享內存
如果需要共享已經存在的命名共享內存映射文件, 使用OpenFileMapping函數。
//OpenFileMapping 打開一個已命名的文件映射對象
HANDLE OpenFileMapping(
DWORD dwDesiredAccess, // 訪問模式
BOOL bInheritHandle, // 繼承標誌
LPCTSTR lpName // 文件映射對象名指針
);
註意:
dwDesiredAccess:訪問模式與MapViewOfFile中的訪問模式相同。
bInheritHandle:繼承標誌,是否可以被一個新的進程繼承使用,如果為TRUE,就可以被一個新進程繼承句柄。
返回值:
成功返回一個已命名的文件映射對象,失敗返回NULL。

3) 獲得地址空間指針
進行內存映射文件的讀寫和一般的文件讀寫不同, 是直接面對你申請的地址空間, 為此需要使用MapViewOfFile得到相關的地址LPVOID類型的指針。如果需要進行文件寫入, 可以通過類型轉換直接對於內存地址進行賦值, 比如:
memcpy( lpAddress, lpBuf, ....)
這裏自然需要防止內存溢出的情況。
如果是讀取操作,將參數順序調整一下就可以了。

MapViewOfFile 在調用進程的地址空間映射一個文件視圖
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 已創建的文件映射對象句柄
DWORD dwDesiredAccess, // 訪問模式
DWORD dwFileOffsetHigh, // 文件偏移的高32位
DWORD dwFileOffsetLow, // 文件偏移的低32位
DWORD dwNumberOfBytesToMap // 映射視圖的大小
);
註意:
hFileMappingObject: 由CreateFileMapping 或 OpenFileMapping 返回的文件映射對象句柄。
dwDesiredAccess:映射視圖的訪問模式,與創建文件映射對象的保護模式flProtect有關,可以被設置為下列值:
FILE_MAP_WRITE:一個可讀寫屬性的文件視圖被創建,保護模式為PAGE_READWRITE
FILE_MAP_READ :一個只讀屬性的文件視圖被創建,保護模式為PAGE_READWRITE 或 PAGE_READONLY
FILE_MAP_ALL_ACCESS:與FILE_MAP_WRITE模式相同
FILE_MAP_COPY:保護模式為PAGE_WRITECOPY時,得到一個視圖文件,當你對視圖文件寫操作時,頁面自動交換,並且你所做的修改不會損壞原始數據資料。
dwNumberOfBytesToMap:映射文件部分的大小,如果為0,則映射整個文件。
返回值:
如果成功返回返回映射視圖的起始地址,如果失敗返回NULL。

4)MapViewOfFileEx 在調用進程的地址空間映射一個文件視圖,並且允許調用進程為映射視圖指定特殊的內存地址
LPVOID MapViewOfFileEx(
HANDLE hFileMappingObject, // 文件映射對象的句柄
DWORD dwDesiredAccess, // 訪問模式
DWORD dwFileOffsetHigh, // 文件偏移的高32位
DWORD dwFileOffsetLow, // 文件偏移的低32位
DWORD dwNumberOfBytesToMap, // 映射視圖的大小
LPVOID lpBaseAddress // 指定映射視圖的其實內存地址
);
註意:
與MapViewOfFile用法相同,但是如果指定的內存地址空間大小不夠,則函數執行失敗。


5) 將內存復制到所映射的物理文件上面
FlushMapViewOfFile函數可以將內存裏面的內容DUMP到物理磁盤上面
FlushViewOfFile 把文件映射視圖中的修改的內容或全部寫回到磁盤文件中
BOOL FlushViewOfFile(
LPCVOID lpBaseAddress, // 修改內容的起始地址
DWORD dwNumberOfBytesToFlush // 修改的字節數目
);
函數執行成功返回非零。

6) 卸載內存映射文件地址指針
UnmapViewOffFile函數就是卸載
UnmapViewOfFile 刪除文件的映射視圖
BOOL UnmapViewOfFile(
LPCVOID lpBaseAddress // 映射視圖起始地址
);
註意:
lpBaseAddress:映射視圖起始地址,由 MapViewOfFile 函數 MapViewOfFileEx產生。
返回值:
如果調用成功返回非零,並且所有指定地址內的臟頁面會被寫入硬盤。調用失敗返回零。

7) 關閉內存映射文件
太簡單了, CloseHandle搞定

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow

CreateFileMapping MapViewOfFile UnmapViewOfFile函數用法及示例