基於visual c++之windows核心編程程式碼分析(22)Mapping File編程

來源:互聯網
上載者:User

檔案對應(mapping)是一種將檔案內容映射到進程的虛擬位址空間的技術。視圖(View)是一段虛擬位址空間,進程可以通過View來存取檔案的內容,視圖是一段記憶體,可以使用指標來操作視圖。使用檔案對應之後,讀寫檔案就如同對讀寫記憶體一樣簡單。在使用檔案對應時需要建立映射對象,映射對象分為命名的和未命名的。映射對象還存取許可權。

       使用檔案對應至少有3個好處,一是因為檔案儲存體與硬碟上的,而檔案視圖是一段記憶體,使用檔案對應操作時更方便;二是效率更高;三是可以在不同的進程間共用資料。     

       檔案對應依賴於系統虛擬記憶體管理的分頁機制。

關鍵API

 GetSystemInfo

擷取系統資訊,在後面的執行個體中用於擷取系統記憶體配置粒度。

CreateFileMapping

建立mapping對象,函數原型如下:/×應該是建立一個檔案對應的核心對象×/

CreateFileMapping(

    HANDLE hFile,

    LPSECURITY_ATTRIBUTES lpAttributes,

    DWORD dwMaximumSizeHigh,

    DWORD dwMaximumSizeLow,

    LPCTSTR lpName

);

參數

       hFile: 輸入參數,由 CreateFile 建立的需要映射的檔案的檔案控制代碼。

       lpAttributes: 輸入參數,指向 SECURITY_ATTRIBUTES結構的指標,在一般情況使用預設屬性即可,將此參數賦為NULL。

       flProtect: 輸入參數,記憶體保護屬性,可以是 PAGE_READONLY 、PAGE_READWRITE、PAGE_WRITECOPY、PAGE_EXECUTE_READ、PAGE_EXECUTE_READWRITE 中的一種,也可以使用位或運算附加下面的屬性:SECURITY_ATTRIBUTES、SEC_COMMIT、SEC_IMAGE、SEC_LARGE_PAGES、SEC_NOCACHE、SEC_RESERVE。

       dwMaximumSizeHigh:輸入參數,映射大小的最大值的高32位。

       dwMaximumSizeLow:輸入參數,映射大小的最大值的低32位。

       lpName:輸入參數,映射對象名,可以是NULL。

傳回值:

       返回HANDLE值,mapping物件控點。如果返回NULL,則表示失敗。可使用GetLastError函數擷取錯誤資訊。

 MapViewOfFile

建立視圖,將檔案mapping 映射到當前進程的虛擬記憶體地址空間。函數原型如下:

LPVOID MapViewOfFile(

    HANDLE hFileMappingObject,

    DWORD dwDesiredAccess,

    DWORD dwFileOffsetHigh,

    DWORD dwFileOffsetLow,

    SIZE_T dwNumberOfBytesToMap

);

參數

      hFileMappingObject:輸入資料,檔案 mapping 對象的控制代碼,由 CreateFileMapping  函數或OpenFileMapping函數返回。

       dwDesiredAccess:輸入參數,存取類別,可以是 FILE_MAP_WRITE、FILE_MAP_READ、FILE_MAP_COPY、、FILE_MAP_EXECUTE中的一種。

       dwFileOffsetHigh:輸入參數,映射的檔案位移的高32位。

       dwFileOffsetLow:輸入參數,映射的檔案位移的低32位。

       dwNumberOfBytesToMap:輸入參數,映射到View的位元組數。

傳回值:

       返回LPVOID值,指向映射的記憶體值,如果為NULL表示錯誤。

FlushViewOfFile

將視圖中的檔案資料寫入到磁碟上。調用此參數後,對映射視圖的記憶體操作將會及時反映到硬碟中的檔案。函數原型如下:

BOOL FlushViewOfFile(

     LPVOID  lpBaseAddress,

     SIZE_T  dwNumberOfBytesToFlush

);

參數

lpBaseAddress:輸入參數,需要寫入至檔案的資料的起始位置。

dwNumberOfBytesToFlush:輸入參數,寫入的位元組數,如果為0則將整個視圖都寫回。

傳回值:

返回BOOL 值,表示是否成功。

使用說明

如果不調用此函數,資料最終也會寫回到硬碟,調用此函數後,資料會立刻寫回到硬碟。

FillMemory、CopyMemory。記憶體操作函數,分別為填充記憶體和複製記憶體。

 

使用Mapping File提高檔案讀寫的效率範例

/* 標頭檔 */<br />#include <windows.h><br />#include <stdio.h><br />/* 預先處理申明 */<br />#define BUFFSIZE 1024// 記憶體大小<br />#define FILE_MAP_START 0x28804// 檔案對應的起始的位置<br />/* 全域變數 */<br />LPTSTR lpcTheFile = TEXT("test.dat");// 檔案名稱</p><p>/* ************************************<br />* int main(void)<br />* 功能示範使用檔案mapping<br />*<br />* 參數無<br />*<br />* 傳回值0代表執行完成,1代表發生錯誤<br />**************************************/<br />int main(void)<br />{<br />HANDLE hMapFile; // 檔案記憶體映射地區的控制代碼<br />HANDLE hFile; // 檔案的控制代碼<br />DWORD dBytesWritten; // 寫入的位元組數<br />DWORD dwFileSize; // 檔案大小<br />DWORD dwFileMapSize; // 檔案對應的大小<br />DWORD dwMapViewSize; // 視圖(View)的大小<br />DWORD dwFileMapStart; // 檔案對應視圖的起始位置<br />DWORD dwSysGran; // 系統記憶體配置的粒度<br />SYSTEM_INFO SysInfo; // 系統資訊<br />LPVOID lpMapAddress; // 內在映射地區的起始位置<br />PCHAR pData;// 資料<br />INT i; // 迴圈變數<br />INT iData;<br />INT iViewDelta;<br />BYTE cMapBuffer[32]; // 儲存從mapping中計出的資料</p><p>// 建立一個檔案<br />hFile = CreateFile(lpcTheFile,<br />GENERIC_READ | GENERIC_WRITE,<br />0,<br />NULL,<br />CREATE_ALWAYS,<br />FILE_ATTRIBUTE_NORMAL,<br />NULL);<br />//判斷檔案是否建立成功<br />if (hFile == INVALID_HANDLE_VALUE)<br />{<br />printf("CreateFile error\n",GetLastError);<br />return 1;<br />}<br />// 依次寫入整數,一共寫入65535個整數<br />// 在32位平台下,大小為65535*32<br />for (i=0; i<65535; i++)<br />{<br />WriteFile (hFile, &i, sizeof (i), &dBytesWritten, NULL);<br />}<br />// 查看寫入完成後的檔案大小<br />dwFileSize = GetFileSize(hFile, NULL);<br />printf("檔案大小: %d\n", dwFileSize);</p><p>//擷取系統資訊,記憶體配置粒度<br />//擷取分配粒度,進行下面的幾個計算,<br />//目的是為了映射的資料與系統記憶體配置粒度對齊,提高記憶體訪問效率<br />GetSystemInfo(&SysInfo);<br />dwSysGran = SysInfo.dwAllocationGranularity;</p><p>//計算mapping的起始位置<br />dwFileMapStart = (FILE_MAP_START / dwSysGran) * dwSysGran;<br />// 計算mapping view的大小<br />dwMapViewSize = (FILE_MAP_START % dwSysGran) + BUFFSIZE;<br />// 計算mapping的大小<br />dwFileMapSize = FILE_MAP_START + BUFFSIZE;<br />// 計算需要讀取的資料的位移<br />iViewDelta = FILE_MAP_START - dwFileMapStart;</p><p>// 建立File mapping<br />hMapFile = CreateFileMapping( hFile, // 需要映射的檔案的控制代碼<br />NULL, // 安全選項:預設<br />PAGE_READWRITE, // 可讀,可寫<br />0, // mapping對象的大小,高位<br />dwFileMapSize, // mapping對象的大小,低位<br />NULL); // mapping對象的名字<br />if (hMapFile == NULL)<br />{<br />printf("CreateFileMapping error: %d\n", GetLastError() );<br />return 1;<br />}</p><p>// 映射view<br />lpMapAddress = MapViewOfFile(hMapFile, // mapping對象的控制代碼<br />FILE_MAP_ALL_ACCESS, // 可讀,可寫<br />0, // 映射的檔案位移,高32位<br />dwFileMapStart, // 映射的檔案位移,低32位<br />dwMapViewSize); // 映射到View的資料大小<br />if (lpMapAddress == NULL)<br />{<br />printf("MapViewOfFile error: %d\n", GetLastError());<br />return 1;<br />}</p><p>printf ("檔案map view相對於檔案的起始位置: 0x%x\n",<br />dwFileMapStart);<br />printf ("檔案map view的大小:0x%x\n", dwMapViewSize);<br />printf ("檔案mapping對象的大小:0x%x\n", dwFileMapSize);<br />printf ("從相對於map view 0x%x 位元組的位置讀取資料,", iViewDelta);</p><p>// 將指向資料的指標位移,到達我們關心的地方<br />pData = (PCHAR) lpMapAddress + iViewDelta;<br />// 讀取資料,賦值給變數<br />iData = *(PINT)pData;<br />// 顯示讀取的資料<br />printf ("為:0x%.8x\n", iData);</p><p>// 從mapping中複製資料,32個位元組,並列印<br />CopyMemory(cMapBuffer,lpMapAddress,32);<br />printf("lpMapAddress起始的32位元組是:");<br />for(i=0; i<32; i++)<br />{<br />printf("0x%.2x ",cMapBuffer[i]);<br />}<br />// 將mapping的前32個位元組用0xff填充<br />FillMemory(lpMapAddress,32,(BYTE)0xff);<br />// 將映射的資料寫回到硬碟上<br />FlushViewOfFile(lpMapAddress,dwMapViewSize);<br />printf("\n已經將lpMapAddress開始的32位元組使用0xff填充。\n");</p><p>// 關閉mapping對象<br />if(!CloseHandle(hMapFile))<br />{<br />printf("\nclosing the mapping object error %d!",<br />GetLastError());<br />}<br />//關閉檔案<br />if(!CloseHandle(hFile))<br />{<br />printf("\nError %ld occurred closing the file!",<br />GetLastError());<br />}</p><p>return 0;<br />}

 

 通過Mapping File在進程間共用記憶體

 

/* 標頭檔 */<br />#include <windows.h><br />#include <stdio.h><br />#include <conio.h><br />/* 預先處理申明 */<br />#define BUF_SIZE 256<br />/* 全域變數 */<br />LPTSTR szName = TEXT("SharedFileMappingObject");<br />LPTSTR szMsg = TEXT("進程的訊息");</p><p>/* ************************************<br />* int main(void)<br />* 功能示範檔案mapping共用記憶體,寫入資料到共用記憶體<br />*<br />* 參數無<br />*<br />* 傳回值0代表執行完成,代表發生錯誤<br />**************************************/<br />void main(int argc, PCHAR argv[])<br />{<br />//檔案對應控制代碼<br />HANDLE hMapFile;<br />//共用資料緩衝區指標<br />LPTSTR pBuf;<br />//建立命名的檔案對應,不代表任務硬碟上的檔案<br />hMapFile = CreateFileMapping(<br />INVALID_HANDLE_VALUE,<br />NULL,<br />PAGE_READWRITE,<br />0,<br />BUF_SIZE,<br />szName);<br />if (hMapFile == NULL || hMapFile == INVALID_HANDLE_VALUE)<br />{<br />printf("CreateFileMapping error: %d\n",GetLastError());<br />return;<br />}<br />//建立View<br />pBuf = (LPTSTR) MapViewOfFile(hMapFile,<br />FILE_MAP_ALL_ACCESS,<br />0,<br />0,<br />BUF_SIZE);<br />if (pBuf == NULL)<br />{<br />printf("MapViewOfFile error %d\n", GetLastError());<br />return;<br />}<br />//將共用資料複製到檔案對應中,如果運行時輸入了參數則使用參數<br />if(argc==1)<br />{<br />CopyMemory((PVOID)pBuf, szMsg, strlen(szMsg));<br />}<br />else<br />{<br />DWORD dwCopyLen = (lstrlen(argv[1])<BUF_SIZE) ? lstrlen(argv[1]): BUF_SIZE;<br />CopyMemory((PVOID)pBuf, argv[1], dwCopyLen);<br />}<br />printf("運行程式,完成運行後,按任意鍵退出。");<br />_getch();<br />//取消映射,退出<br />UnmapViewOfFile(pBuf);<br />CloseHandle(hMapFile);<br />}

通過Mapping File在進程間共用記憶體通過Mapping File在進程間共用記憶體通過Mapping File在進程間共用記憶體

#include <windows.h><br />#include <stdio.h><br />#include <conio.h><br />/* 預先處理申明*/<br />#pragma comment (lib, "User32.lib")<br />#define BUF_SIZE 256<br />/* 全域變數 */<br />TCHAR szName[]=TEXT("SharedFileMappingObject");</p><p>/* ************************************<br />* int main(void)<br />* 功能示範檔案mapping共用記憶體,從共用資料中讀資訊<br />*<br />* 參數無<br />*<br />* 傳回值0代表執行完成,代表發生錯誤<br />**************************************/<br />void main()<br />{<br />HANDLE hMapFile;<br />LPTSTR pBuf;<br />//開啟檔案mapping<br />hMapFile = OpenFileMapping(<br />FILE_MAP_ALL_ACCESS,<br />FALSE,<br />szName);<br />if (hMapFile == NULL)<br />{<br />printf("OpenFileMapping error: %d.\n", GetLastError());<br />return;<br />}<br />//映射<br />pBuf = MapViewOfFile(hMapFile,<br />FILE_MAP_ALL_ACCESS,<br />0,<br />0,<br />BUF_SIZE);<br />if (pBuf == NULL)<br />{<br />printf("MapViewOfFile error %d\n", GetLastError());<br />return;<br />}<br />//訊息得到的共用資料<br />MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);<br />//取消mapping,關閉控制代碼,返回<br />UnmapViewOfFile(pBuf);<br />CloseHandle(hMapFile);<br />}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.