記憶體對應檔記憶體對應檔的3種用途:1 載入.exe 或者DLL2 用記憶體對應檔來訪問磁碟上的檔案3 處理序間通訊
1 執行程式.exe 一般載入的基地址是0X00400000,而DLL一般載入的基地址是0X10000000.
2 同一個執行程式或者DLL的多個執行個體,不會共用待用資料。
3 .exe 和DLL 使用的記憶體頁面屬性是寫時複製。
怎麼在同一個執行程式或者DLL的不同執行個體,來共用待用資料呢?比如想知道,同一個程式,運行了多個執行個體!
使用EXE檔案結構的段資訊。“Shared” 表示共用段 多個執行個體都共用
#pragma data_seg("Shared")
volatile LONG g_lApplicationInstances = 0;
#pragma data_seg()
// Tell the linker to make the Shared section readable, writable, and shared.
#pragma comment(linker, "/Section:Shared,RWS")
/******************************************************************************Module: AppInst.cppNotices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre******************************************************************************/#include "..\CommonFiles\CmnHdr.h" /* See Appendix A. */#include <windowsx.h>#include <tchar.h>#include "Resource.h"///////////////////////////////////////////////////////////////////////////////// The system-wide window message, unique to the applicationUINT g_uMsgAppInstCountUpdate = WM_APP+123;///////////////////////////////////////////////////////////////////////////////// Tell the compiler to put this initialized variable in its own Shared // section so it is shared by all instances of this application.#pragma data_seg("Shared")volatile LONG g_lApplicationInstances = 0;#pragma data_seg()// Tell the linker to make the Shared section readable, writable, and shared.#pragma comment(linker, "/Section:Shared,RWS")///////////////////////////////////////////////////////////////////////////////BOOL Dlg_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam) { chSETDLGICONS(hWnd, IDI_APPINST); // Force the static control to be initialized correctly. PostMessage(HWND_BROADCAST, g_uMsgAppInstCountUpdate, 0, 0); return(TRUE);}///////////////////////////////////////////////////////////////////////////////void Dlg_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify) { switch (id) { case IDCANCEL: EndDialog(hWnd, id); break; }}///////////////////////////////////////////////////////////////////////////////INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == g_uMsgAppInstCountUpdate) { SetDlgItemInt(hWnd, IDC_COUNT, g_lApplicationInstances, FALSE); } switch (uMsg) { chHANDLE_DLGMSG(hWnd, WM_INITDIALOG, Dlg_OnInitDialog); chHANDLE_DLGMSG(hWnd, WM_COMMAND, Dlg_OnCommand); } return(FALSE);}///////////////////////////////////////////////////////////////////////////////int WINAPI _tWinMain(HINSTANCE hInstExe, HINSTANCE, PTSTR, int) { // Get the numeric value of the systemwide window message used to notify // all top-level windows when the module's usage count has changed. g_uMsgAppInstCountUpdate = RegisterWindowMessage(TEXT("MsgAppInstCountUpdate")); // There is another instance of this application running InterlockedExchangeAdd(&g_lApplicationInstances, 1); DialogBox(hInstExe, MAKEINTRESOURCE(IDD_APPINST), NULL, Dlg_Proc); // This instance of the application is terminating InterlockedExchangeAdd(&g_lApplicationInstances, -1); // Have all other instances update their display PostMessage(HWND_BROADCAST, g_uMsgAppInstCountUpdate, 0, 0); return(0);}//////////////////////////////// End of File //////////////////////////////////
2 映射到記憶體的資料檔案
使用記憶體對應檔1 建立或者開啟檔案核心對象CreateFile 建立或者開啟一個檔案,函數詳情見MSDN
2 建立一個檔案對應記憶體對象HANDLE
WINAPI
CreateFileMappingA(
__in HANDLE hFile, 建立的檔案核心對象
__in_opt LPSECURITY_ATTRIBUTES lpFileMappingAttributes, 安全屬性一般為NULL
__in DWORD flProtect, 保護屬性
__in DWORD dwMaximumSizeHigh, 檔案大小高位元組,檔案大於4G,才需要用到
__in DWORD dwMaximumSizeLow, 檔案大小低位元組,相當於檔案大小,如果這個2個參數都為0,使用檔案核心對象的檔案大小
__in_opt LPCSTR lpName 檔案對應物件名稱,可以用來在不同進程間共用
);
3 把檔案對應物件的資料對應到進程地址空間LPVOID
WINAPI
MapViewOfFile(
__in HANDLE hFileMappingObject, // 檔案對應核心對象
__in DWORD dwDesiredAccess, 存取權限
__in DWORD dwFileOffsetHigh, 檔案位移量高位元組
__in DWORD dwFileOffsetLow, 低位元組,必須是64KB整數倍
__in SIZE_T dwNumberOfBytesToMap 需要映射的位元組大小
);
MapVieOfFileEx 可以用於記憶體對應檔是鏈表的情況。
用完記憶體映射對象後,必須清理釋放。1 取消進程地址空間到檔案對應物件的關聯BOOL UnmapViewOfFile(PLVOID pvBaseAddress);參數是調用MapViewOfFile返回的地址。
2 關閉檔案對應核心對象CloseHandle3 關閉檔案核心對象CloseHandle
範例程式碼:
// MemoryMapFile.cpp : Defines the entry point for the console application.//#include <Windows.h>#include <process.h>#include <tchar.h>int _tmain(int argc, _TCHAR* argv[]){int len = sizeof(TCHAR);HANDLE hFile = CreateFile(TEXT("1.txt"),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);DWORD dwSize = GetFileSize(hFile,NULL);//建立檔案對應記憶體HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE,0,dwSize + 1,NULL);//建立映射視圖LPSTR lpstr = (LPSTR)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0,/*檔案指標位移量*/0,0 /*Use fileSize*/);lpstr[dwSize] = 0;_strrev(lpstr);//重新整理視圖FlushViewOfFile(lpstr, 10);//斷開視圖映射UnmapViewOfFile(lpstr);CloseHandle(hMapFile);SetFilePointer(hFile,dwSize,NULL,FILE_BEGIN);SetEndOfFile(hFile);CloseHandle(hFile);return 0;}
用記憶體對應檔在進程中共用資料
以頁分頁檔為儲存空間的記憶體對應檔
在調用CreateFileMapping時,第一個參數傳 INVALID_HANDLE_VALUE就可以了,大小是參數4,參數5.
// MemoryMapFile.cpp : Defines the entry point for the console application.//#include <Windows.h>#include <process.h>#include <tchar.h>#include <stdio.h>int _tmain(int argc, _TCHAR* argv[]){const DWORD dwSize = 4 * 1024;//建立檔案對應記憶體HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,0,dwSize,TEXT("111"));if(ERROR_ALREADY_EXISTS == GetLastError()){printf("exists\n");hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, TEXT("111"));//建立映射視圖PTCHAR lpstr = (PTCHAR)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0,/*檔案指標位移量*/0,0 /*Use fileSize*/);printf("%S\n",lpstr);goto leave;}//建立映射視圖PTCHAR lpstr = (PTCHAR)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0,/*檔案指標位移量*/0,0 /*Use fileSize*/);_tcscpy(lpstr,TEXT("123456"));//重新整理視圖FlushViewOfFile(lpstr, 10);leave://斷開視圖映射UnmapViewOfFile(lpstr);getchar();CloseHandle(hMapFile);return 0;}