Windows 核心编程 17 内存映射文件

内存映射文件

内存映射文件的3种用途:
1 载入.exe 或者DLL
2 用内存映射文件来访问磁盘上的文件
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.cpp
Notices: 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 application
UINT 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 关闭文件映射内核对象
CloseHandle
3 关闭文件内核对象
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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值