序
Microsoft Windows 提供了三種機制來對記憶體進行操作。
1、堆-----------最適合用來管理大量的小型對象。
2、虛擬記憶體-----最適合用來管理大型物件數組或大型結構數組。
3、記憶體對應檔-最適合用來管理大型資料流(通常是檔案),以及在同一機器上啟動並執行多個進程之間共用資料。
接下來我給大家介紹一下記憶體對應檔的相關知識。
記憶體對應檔相關知識介紹
與虛擬記憶體相似,記憶體對應檔允許開發人員預定一塊地址空間地區並給地區調撥實體儲存體器。
不同之處在於,記憶體對應檔的實體儲存體器來自磁碟上已有的檔案,而不是來自系統的頁分頁檔。
一旦把檔案對應到地址空間,我們就可以對它進行訪問,就好像整個檔案都已經被載入記憶體一樣。
記憶體對應檔主要用於以下三種情況。
1、系統使用記憶體對應檔來載入並運行.exe和動態連結程式庫(DLL)檔案。這大量節省了頁分頁檔的
空間以及應用程式啟動的時間。
2、開發人員可以用記憶體對應檔來訪問磁碟上的資料檔案。這使得我們可以避免直接對檔案進行
I/O操作和對檔案內容進行緩衝。
3、通過使用記憶體對應檔,我們可以在同一台機器的不同進程之間共用資料。Windows的確提供了
其他的一些方法來在進程間傳送資料,但這些方法都是通過記憶體對應檔來實現的。因此,如果在
同一台機器的不同進程之間共用資料,記憶體對應檔是最高效的方法。
使用記憶體對應檔的步驟:
1、建立或開啟一個檔案核心對象,該對象標識了我們想要用作記憶體對應檔的那個磁碟檔案。
CreateFile();
2、建立一個檔案對應核心對象,來告訴系統檔案的大小以及我們打算如何訪問檔案。
CreateFileMapping();
3、告訴系統把檔案對應物件的部分或全部映射到進程的地址空間中。
MapViewOfFile();
用完記憶體對應檔之後,必須執行以下三步進行清理。
1、告訴系統從進程地址空間中取消對檔案對應核心對象的映射。
UnmapViewOfFile();
2、關閉檔案對應核心對象。
CloseHandle();
3、關閉檔案核心對象。
CloseHandle();
上邊說的很複雜,其實使用起來很簡單的,下邊是我根據windows核心編程改寫的一個案例。
案例
/************************************************************************//* 記憶體映射一 *//*程式示範了如何把一個已存在的檔案對應到記憶體中,並倒轉檔案內容 *//*轉載請註明文章來自:http://blog.csdn.net/windows_nt *///************************************************************************/#include <Windows.h>#include <tchar.h>#include <string.h> // For _strrev#include <iostream>#include <CommDlg.h>typedef TCHAR *PTSTR;#define FILENAME TEXT("FILEREV.DAT")BOOL FileReverse(PCTSTR pszPathname, PBOOL pfIsTextUnicode) { *pfIsTextUnicode = FALSE; // Assume text is Unicode // Open the file for reading and writing. HANDLE hFile = CreateFile(pszPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("File could not be opened."); return(FALSE); } // Get the size of the file (I assume the whole file can be mapped). DWORD dwFileSize = GetFileSize(hFile, NULL); // Create the file-mapping object. The file-mapping object is 1 character // bigger than the file size so that a zero character can be placed at the // end of the file to terminate the string (file). Because I don't yet know // if the file contains ANSI or Unicode characters, I assume worst case // and add the size of a WCHAR instead of CHAR. HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize + sizeof(WCHAR), NULL); if (hFileMap == NULL) { printf("File map could not be opened."); CloseHandle(hFile); return(FALSE); } // Get the address where the first byte of the file is mapped into memory. PVOID pvFile = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0); if (pvFile == NULL) { printf("Could not map view of file."); CloseHandle(hFileMap); CloseHandle(hFile); return(FALSE); } // Does the buffer contain ANSI or Unicode? int iUnicodeTestFlags = -1; // Try all tests *pfIsTextUnicode = IsTextUnicode(pvFile, dwFileSize, &iUnicodeTestFlags); if (!*pfIsTextUnicode) { // For all the file manipulations below, we explicitly use ANSI // functions because we are processing an ANSI file. // Put a zero character at the very end of the file. PSTR pchANSI = (PSTR) pvFile; pchANSI[dwFileSize / sizeof(CHAR)] = 0; // Reverse the contents of the file. _strrev(pchANSI); // Convert all "\n\r" combinations back to "\r\n" to // preserve the normal end-of-line sequence. pchANSI = strchr(pchANSI, '\n'); // Find first '\n'. while (pchANSI != NULL) { // We have found an occurrence.... *pchANSI++ = '\r'; // Change '\n' to '\r'. *pchANSI++ = '\n'; // Change '\r' to '\n'. pchANSI = strchr(pchANSI, '\n'); // Find the next occurrence. } } else { // For all the file manipulations below, we explicitly use Unicode // functions because we are processing a Unicode file. // Put a zero character at the very end of the file. PWSTR pchUnicode = (PWSTR) pvFile; pchUnicode[dwFileSize / sizeof(WCHAR)] = 0; if ((iUnicodeTestFlags & IS_TEXT_UNICODE_SIGNATURE) != 0) { // If the first character is the Unicode BOM (byte-order-mark), // 0xFEFF, keep this character at the beginning of the file. pchUnicode++; } // Reverse the contents of the file. _wcsrev(pchUnicode); // Convert all "\n\r" combinations back to "\r\n" to // preserve the normal end-of-line sequence. pchUnicode = wcschr(pchUnicode, L'\n'); // Find first '\n'. while (pchUnicode != NULL) { // We have found an occurrence.... *pchUnicode++ = L'\r'; // Change '\n' to '\r'. *pchUnicode++ = L'\n'; // Change '\r' to '\n'. pchUnicode = wcschr(pchUnicode, L'\n'); // Find the next occurrence. } } // Clean up everything before exiting. UnmapViewOfFile(pvFile); CloseHandle(hFileMap); // Remove trailing zero character added earlier. SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN); SetEndOfFile(hFile); CloseHandle(hFile); return(TRUE);}void main(){//目前的目錄下,必須是數字或字母且為斷行符號結束,不然,轉換出來是亂碼PTCHAR szPathname = _T("123.txt");// Make copy of input file so that we don't destroy itif (!CopyFile(szPathname, FILENAME, FALSE)) {printf("New file could not be created.");return;}BOOL fIsTextUnicode;if (FileReverse(FILENAME, &fIsTextUnicode)) {// Spawn Notepad to see the fruits of our labors.STARTUPINFO si = { sizeof(si) };PROCESS_INFORMATION pi;TCHAR sz[] = TEXT("Notepad ") FILENAME;if (CreateProcess(NULL, sz,NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {CloseHandle(pi.hThread);CloseHandle(pi.hProcess);}} DeleteFile(FILENAME);return;}