WIN32汇编语言教程:第10章 内存管理和文件操作 · 10.4 内存映射文件(3)
_CountWord proc local @hFile,@hFileMap,@lpMemory,@dwFileSize local @szLogFile[MAX_PATH]:byte local @szBuffer invoke RtlZeroMemory,addr stWordCount,sizeof stWordCount ;******************************************************************** ; 打开文件 ;******************************************************************** invoke CreateFile,addr szFileName,GENERIC_READ,\ FILE_SHARE_READ,0,\ OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if eax == INVALID_HANDLE_VALUE jmp _Error .endif mov @hFile,eax invoke GetFileSize,@hFile,NULL mov @dwFileSize,eax ;******************************************************************** ; 建立内存映射文件并处理每个字节 ;******************************************************************** invoke CreateFileMapping,@hFile,NULL,PAGE_READONLY,0,0,NULL .if eax mov @hFileMap,eax invoke MapViewOfFile,eax,FILE_MAP_READ,0,0,0 .if eax mov @lpMemory,eax jmp @F .endif invoke CloseHandle,@hFileMap .endif jmp _Error @@: ;******************************************************************** ; 处理文件内容 ;******************************************************************** xor eax,eax mov dwCount,eax mov esi,@lpMemory mov edi,offset stWordCount .while @dwFileSize lodsb dec @dwFileSize invoke _CountLetter,eax .endw invoke _CountLetter,0 ;******************************************************************** ; 关闭内存映射文件 ;******************************************************************** invoke UnmapViewOfFile,@lpMemory invoke CloseHandle,@hFileMap invoke CloseHandle,@hFile ;******************************************************************** ; 输出记录文件 ;******************************************************************** ...
读者可以在所附光盘的Chapter10\WordCount\FileMap目录中找到修改后的源程序。对比原来的程序可以看出,除了多了几句建立内存映射文件的代码外,程序中真正用于处理数据的代码结构要简单很多。
3. 使用内存映射文件在进程间共享数据
先来看一个例子文件,例子在所附光盘的Chapter10\MMFShare目录下。首先多次执行目录中的MMFShare.exe文件,然后尝试在不同执行副本中的编辑框中输入字符,读者马上可以发现,不管在哪个副本中输入字符,所有副本的文本框中都会被设置成刚刚输入的内容(如图10.9所示),这就是用内存映射文件实现的。
图10.9 使用MMF进行进程间共享
使用内存映射文件在进程间共享数据的步骤如下:
(1)调用OpenFileMapping打开一个命名的内存映射文件对象,得到hFileMap。如果打开成功则跳到步骤(3),如果打开不成功,则表示本进程是执行的第一个副本,那么继续执行步骤(2)。
(2)调用CreateFileMapping函数创建一个命名的内存映射对象,得到hFileMap。
(3)调用MapViewOfFile函数映射对象的一个视图,得到指向映射到内存的第一个字节的指针lpMemory。
(4)用该指针来读写共享的内存区域。
(5)调用UnmapViewOfFile来解除视图映射,传入参数为lpMemory
(6)调用CloseHandle来关闭内存映射文件,传入参数为hFileMap。
上面的步骤与映射普通的磁盘文件相比,少了打开和关闭文件的步骤,但多了一个OpenFileMapping的步骤。还有一个区别在于,建立内存映射文件对象的时候使用的不是文件句柄,而是使用命名的方法。
具体的实现方法参见例子文件MMFShare.asm中的源代码:
.386 .model flat, stdcall option casemap :none ;#################################################################### ; Include 文件定义 ;#################################################################### include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib ;#################################################################### ; Equ 等值定义 ;#################################################################### ICO_MAIN equ 1000 DLG_MAIN equ 100 IDC_TXT equ 101 IDC_INFO equ 102 ;#################################################################### ; 数据段 ;#################################################################### .data? hInstance dd ? hWinMain dd ? hFileMap dd ? lpMemory dd ? .const szErr db '无法建立内存共享文件',0 szMMFName db 'MMF_Share_Example',0 ;#################################################################### ; 代码段 ;#################################################################### .code ;#################################################################### _CreateMMF proc invoke OpenFileMapping,FILE_MAP_READ or FILE_MAP_WRITE,\ 0,addr szMMFName .if ! eax invoke CreateFileMapping,-1,NULL,PAGE_READWRITE,0,\ 4096,addr szMMFName .if ! eax jmp @F .endif .endif mov hFileMap,eax invoke MapViewOfFile,eax,FILE_MAP_READ or FILE_MAP_WRITE,\ 0,0,0 .if eax mov lpMemory,eax mov dword ptr [eax],0 ret .endif invoke CloseHandle,hFileMap @@: invoke MessageBox,hWinMain,addr szErr,NULL,MB_OK invoke EndDialog,hWinMain,-1 ret
上页:第10章 内存管理和文件操作 · 10.4 内存映射文件(2) 下页:第10章 内存管理和文件操作 · 10.4 内存映射文件(4)