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)

第10章 内存管理和文件操作

版权所有 © 云南伯恩科技 证书:粤ICP备09170368号