内存映射文件 续

2005
新的一年来到了,2004年12月31号的晚上收到很多的祝福,心里很感激我的朋友们。我的培训也告一段落了。回单位后要面临正式的工作了,大嘴昨天发信息说在学校的兄弟们过得很好,他们的BOSS还请他们堕落了一晚。呵呵,好想回到学校~~~在家呆了两天觉得也没有什么意思,还是决定看看书学习一下吧。接着把内存映射文件消化掉吧。
使用内存映射文件的步骤分两步:
1 使用CreatFileMapping创建一个内存映射文件对象。
Invoke  CreatFileMapping,hFile,lpFilemappingAttributes, flProtect,dwMaximumSizeHigh,/
dwMaximumSizeLow ,lpName
.if eax
mov hFileMap,eax
.endif
这个函数确定了映射文件的用途:是在磁盘文件建立内存映射文件还是在内存页面上建立进程间共享的映射。通过设置第一个参数hFile的值可以实现上面的功能。如果hFile句柄是属于一个已经打开的文件,那么映射文件就在这个文件上建立。如果想建立存在于内存文件中内存映射文件供不同进程共享,则将hFile指定为—1。
lpFilemappingAttributes:内存映射文件对象是否可以被继承。不被继承使用NULL。
flProtect:             内存映射文件的保护方式,注意要在用CreatFile函数打开文件获得hFile句柄的时候必须指定相应的标志
flProtect,dwMaximumSizeHigh/dwMaximumSizeLow::指定64位内存映射文件的长度。将这两参数设置为零,系统会自动将内存映射文件的大小调整到磁盘文件的大小。
lpName: 内存映射文件的名字。用于进程共享的时候映射文件必须起名字。
使用OpenFileMapping打开已经建立的用于进程共享的内存映射文件。 
      Invoke   OpenFileMapping,dwDesiredAccess,bInheritHandle, lpName
      .if       eax
               Mov hFileMap,eax
      .endif
dwDesiredAccess:指定保护类型。
lpName        :创建对象时使用的名字。
bInheritHandle:   继承文件的句柄。
2 创建内存映射文件的一个视图。相当于给内存映射文件分配线形地址空间,并将线形地址与文件的内容相关联。这样应用程序可以通过存取线形地址来存取文件。
Invoke  MapViewOfFile,hFileMap,dwDesiredAccess,dwFileOffsetHigh,dwFileOffsetLow,/
            dwNumberOfBytesToMap
.if eax
        Mov ipMemory,eax
.endif
不多说了这个函数的参数很简单。
取消映射文件:invoke UnmapViewOfFile,lpMemory
关闭映射文件:invoke CloseHandle,hFileMap
吃饭喽:)下午接着来!~
哈哈,我来了~~~中午睡上一小觉真是舒服:)天气不错啊!可是不是晚上,要不然也会学着猴子说上一句:月光不错啊,清泉石上流~~~~~~~~~hiahia
补充一下:将对文件的修改立即写到磁盘上是调用这个函数实现的
Invoke FlushViewOfFile,lpMemory,dwFileSize
不知道你的思路有没有被我打乱:)现在总结一下
使用内存映射文件进行读写文件的步骤:
1. 调用CreatFile打开想要映射的文件,获得hFile
2. 调用CreatFileMapping函数生成一个建立在CreatFile函数创建的文件对象基础上的内存映射对象,得到hFileMap
3. 调用MapViewOfFile函数把整个文件的一个区域或者整个区域映射到内存中,得到指向映射到内存的第一个字节的指针lpMemory
4. 用该指针来读写文件
5. 调用UnmapViewOfFile来解除文件映射,传入参数为lpMemory
6. 调用CloseHandle来关闭内存映射文件,传入参数为hFileMap
7. 调用CloseHandle来关闭文件,传入函数为hFile
下面来看看罗云彬《Windows32汇编程序设计》中的例子:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming >
; by 罗云彬,  ::URL:: http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; WordCount.asm
; 文件读写例子 —— 打开文本文件进行单词统计,然后创建结果文件
; 读写文件操作使用内存映射文件函数。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff WordCount.asm
; rc WordCount.rc
; Link /subsystem:windows WordCount.obj WordCount.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .386
        .model flat, stdcall
        option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include        windows.inc
include        user32.inc
includelib    user32.lib
include        kernel32.inc
includelib    kernel32.lib
include        comdlg32.inc
includelib    comdlg32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN    equ        1000
DLG_MAIN    equ        100
IDC_FILE    equ        101
IDC_BROWSE    equ        102

WORD_COUNT    struct

lpLetter    dd    26 dup (?)
dwCount        dd    ?
dwDepth        dd    ?

WORD_COUNT    ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .data?

hInstance    dd    ?
hWinMain    dd    ?
szFileName    db    MAX_PATH dup (?)
szBuffer    db    4096 dup (?)
stWordCount    WORD_COUNT    <>
dwCount        dd    ?

dwOption    dd    ?
F_COUNTING    equ    00000001h
F_FILEEND    equ    00000002h

        .const
szFileExt    db    '全部文件',0,'*.*',0,0
szLogExt    db    '.log',0
szErrOpenFile    db    '无法打开文件!',0
szErrCreateFile    db    '无法建立记录文件!',0
szFmtWord    db    '%5d (%3d‰) %s',0dh,0ah,0
szSuccees    db    '统计成功,请查看记录文件%s',0
szSucceesCap    db    '统计成功',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

        .code

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 遍历树并输出结果
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WalkTree    proc    _hFile,_lpWC,_lpsz
        local    @dwTemp
        local    @szWord[52]:byte

        pushad
        mov    esi,_lpWC
        assume    esi tr WORD_COUNT
        .if    [esi].dwDepth && [esi].dwCount
;********************************************************************
; 计算百分比并写入log文件
;********************************************************************
            mov    eax,[esi].dwCount
            mov    ecx,1000
            mul    ecx
            mov    ecx,dwCount
            .if    ecx
                div    ecx
            .else
                mov    eax,0
            .endif
            invoke    wsprintf,addr szBuffer,addr szFmtWord,[esi].dwCount,eax,_lpsz
            invoke    lstrlen,addr szBuffer
            mov    ecx,eax
            invoke    WriteFile,_hFile,addr szBuffer,ecx,addr @dwTemp,NULL
        .endif
;********************************************************************
; 如果有下层节点则递规调用
;********************************************************************
        mov    @dwTemp,0
        .while    @dwTemp < 26
            mov    ebx,@dwTemp
            mov    ebx,dword ptr [esi+ebx*4]
            .if    ebx
                invoke    lstrcpy,addr @szWord,_lpsz
                invoke    lstrlen,addr @szWord
                lea    ecx,@szWord
                add    ecx,eax
                mov    eax,@dwTemp
                add    al,'a'
                mov    word ptr [ecx],ax
                invoke    _WalkTree,_hFile,ebx,addr @szWord
            .endif
            inc    @dwTemp
        .endw
;********************************************************************
; 释放节点
;********************************************************************
        .if    [esi].dwDepth
            invoke    GlobalFree,esi
        .endif
        popad
        assume    esi tr WORD_COUNT
        ret

_WalkTree    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 根据数据建立树节点或增加节点计数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CountLetter    proc    _dwLetter
        local    @dwIndex

        assume    edi tr WORD_COUNT
        or    al,20h                ;转换成小写字母
        .if    (al >= 'a') && (al <= 'z')    ;字母
;********************************************************************
; 如果是字母则按edi指针继续搜寻下一节点,找到则更新指针,
; 未找到则建立一个新的节点
;********************************************************************
            sub    al,'a'
            movzx    eax,al
            .if    dword ptr [edi+eax*4]
                mov    edi,dword ptr [edi+eax*4]
            .else
                mov    ebx,[edi].dwDepth
                .if    ebx <    50
                    push    eax
                    invoke    GlobalAlloc,GPTR,sizeof WORD_COUNT
                    pop    ecx
                    .if    eax
                        mov    dword ptr [edi+ecx*4],eax
                        mov    edi,eax
                        inc    ebx
                        mov    [edi].dwDepth,ebx
                    .endif
                .endif
            .endif
        .else
;********************************************************************
; 不是字母表示一个单词已结束,增加单词计数
;********************************************************************
            inc    [edi].dwCount
            .if    [edi].dwDepth
                inc    dwCount
            .endif
            mov    edi,offset stWordCount
        .endif
        assume    edi:nothing
        ret

_CountLetter    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_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
;********************************************************************
; 输出记录文件
;********************************************************************
        invoke    lstrcpy,addr @szLogFile,addr szFileName
        invoke    lstrcat,addr @szLogFile,addr szLogExt
        invoke    CreateFile,addr @szLogFile,GENERIC_WRITE,FILE_SHARE_READ,/
            0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
        .if    eax !=    INVALID_HANDLE_VALUE
            mov    @hFile,eax
            mov    @szBuffer,0
            mov    edi,offset stWordCount
            invoke    _WalkTree,@hFile,edi,addr @szBuffer
            invoke    CloseHandle,@hFile
            invoke    wsprintf,addr szBuffer,addr szSuccees,addr @szLogFile
            invoke    MessageBox,hWinMain,addr szBuffer,addr szSucceesCap,MB_OK or MB_ICONINFORMATION
        .else
            invoke    MessageBox,hWinMain,addr szErrCreateFile,NULL,MB_OK or MB_ICONEXCLAMATION
        .endif
        ret
_Error:
        invoke    MessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONEXCLAMATION
        ret


_CountWord    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain    proc    uses ebx edi esi hWnd,wMsg,wParam,lParam
        local    @stOpenFileName:OPENFILENAME

        mov    eax,wMsg
        .if    eax ==    WM_CLOSE
            .if    ! (dwOption & F_COUNTING)
                invoke    EndDialog,hWnd,NULL
            .endif
;********************************************************************
        .elseif    eax ==    WM_INITDIALOG
            push    hWnd
            pop    hWinMain
            invoke    LoadIcon,hInstance,ICO_MAIN
            invoke    SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
            invoke    SendDlgItemMessage,hWnd,IDC_FILE,EM_SETLIMITTEXT,MAX_PATH,0
;********************************************************************
        .elseif    eax ==    WM_COMMAND
            mov    eax,wParam
            .if    ax ==    IDC_BROWSE
;********************************************************************
                invoke    RtlZeroMemory,addr @stOpenFileName,sizeof OPENFILENAME
                mov    @stOpenFileName.lStructSize,SIZEOF @stOpenFileName
                mov    @stOpenFileName.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
                push    hWinMain
                pop    @stOpenFileName.hwndOwner
                mov    @stOpenFileName.lpstrFilter,offset szFileExt
                mov    @stOpenFileName.lpstrFile,offset szFileName
                mov    @stOpenFileName.nMaxFile,MAX_PATH
                invoke    GetOpenFileName,addr @stOpenFileName
                .if    eax
                    invoke    SetDlgItemText,hWnd,IDC_FILE,addr szFileName
                .endif
;********************************************************************
            .elseif    ax ==    IDC_FILE
                invoke    GetDlgItemText,hWnd,IDC_FILE,addr szFileName,MAX_PATH
                mov    ebx,eax
                invoke    GetDlgItem,hWnd,IDOK
                invoke    EnableWindow,eax,ebx
;********************************************************************
            .elseif    ax ==    IDOK
                invoke    GetDlgItem,hWnd,IDC_FILE
                invoke    EnableWindow,eax,FALSE
                invoke    GetDlgItem,hWnd,IDC_BROWSE
                invoke    EnableWindow,eax,FALSE
                invoke    GetDlgItem,hWnd,IDOK
                invoke    EnableWindow,eax,FALSE
                or    dwOption,F_COUNTING
                call    _CountWord
                and    dwOption,not (F_COUNTING or F_FILEEND)
                invoke    GetDlgItem,hWnd,IDC_FILE
                invoke    EnableWindow,eax,TRUE
                invoke    GetDlgItem,hWnd,IDC_BROWSE
                invoke    EnableWindow,eax,TRUE
                invoke    GetDlgItem,hWnd,IDOK
                invoke    EnableWindow,eax,TRUE
            .endif
;********************************************************************
        .else
            mov    eax,FALSE
            ret
        .endif
        mov    eax,TRUE
        ret

_ProcDlgMain    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
        invoke    GetModuleHandle,NULL
        mov    hInstance,eax
        invoke    DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
        invoke    ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        end    start
本来下午是要把整个内存映射文件看完的可是一个莫名奇妙的会把什么都打乱了~!ft~吃完晚饭回来可能还要c一会,可惜不能跟学长还有老迷,b骆小黑皮豆豆们pk了。哥哥进步很快的啊:)所以先把这个发到blog上吧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值