彙編教程之記憶體對應檔

來源:互聯網
上載者:User

本課中我們將要講解記憶體對應檔並且示範如何運用它。您將會發現使用記憶體對應檔是非常簡單的。

理論:

如果您仔細地研究了前一課的例子, 就會發現它有一個嚴重的缺陷:如果您想讀的內容大於系統分配的記憶體塊怎麼辦?如果您想搜尋的字串剛好超過記憶體塊的邊界又該如何處理?對於第一個問題,您也許會說,只要不斷地讀就不解決了嗎。至於第二個問題,您又會說在記憶體塊的邊界處做一些特別的處理,譬如放上一些標誌位就可以了。原理上確實是行得通,但是這隨問題複雜程度加深而顯得非常難以處理。其中的第二個問題是有名的邊界判斷問題,程式中許許多多的錯誤都是由此引起。想一想,如果我們能夠分配一個能夠容納整個檔案的大記憶體塊該多好啊,這樣這兩個問題不都迎刃而解了嗎?是的,WIN32的記憶體對應檔確實允許我們分配一個裝得下現實中可能存在的足夠大的檔案的記憶體。

利用記憶體對應檔您可以認為作業系統已經為您把檔案全部裝入了記憶體,然後您只要移動檔案指標進行讀寫即可了。這樣您甚至不需要調用那些分配、釋放記憶體塊和檔案輸入/輸出的API函數,另外您可以把這用作不同的進程之間共用資料的一種辦法。運用記憶體對應檔實際上沒有涉及實際的檔案操作,它更象為每個進程保留一個看得見的記憶體空間。至於把記憶體對應檔當成進程間共用資料的辦法來用,則要加倍小心,因為您不得不處理資料的同步問題,否則您的應用程式也許很可能得到過時或錯誤的資料甚至崩潰。本課中我們將主要講述記憶體對應檔,將不涉及進程間的同步。WIN32中的記憶體對應檔應用非常廣泛,譬如:即使是系統的核心模組---PE格式檔案裝載器也用到了記憶體對應檔,因為PE格式的檔案並不是一次性載入到記憶體中來的,譬如他它在首次載入時只載入必需載入的部分,而其他部分在用到時再載入,這正好可以利用到記憶體對應檔的長處。實際中的大多數檔案存取都和PE載入器類似,所以您在處理該類問題時也應該充分利用記憶體對應檔。

記憶體對應檔本身還是有一些局限性的,譬如一旦您產生了一個記憶體對應檔,那麼您在那個會話期間是不能夠改變它的大小的。所以記憶體對應檔對於唯讀檔案和不會影響其大小的檔案操作是非常有用的。當然這並不意味著對於會引起改變其大小的檔案操作就一定不能用記憶體影射檔案的方法,您可以事先估計操作後的檔案的可能大小,然後產生這麼大小一塊的記憶體對應檔,然後檔案的長度就可以增長到這麼一個大小。 我們的解釋夠多的了,接下來我們就看看實現的細節:

調用CreateFile開啟您想要映射的檔案。

調用CreateFileMapping,其中要求傳入先前CreateFile返回的控制代碼,該函數產生一個建立在CreateFile函數建立的檔案對象基礎上的記憶體映射對象。

調用MapViewOfFile函數映射整個檔案的一個地區或者整個檔案到記憶體。該函數返回指向映射到記憶體的第一個位元組的指標。

用該指標來讀寫檔案。

調用UnmapViewOfFile來解除檔案對應。

調用CloseHandle來關閉記憶體對應檔。注意必須傳入記憶體對應檔的控制代碼。

調用CloseHandle來關閉檔案。注意必須傳入由CreateFile建立的檔案的控制代碼。

例子:

下面的例子允許使用者通過“開啟檔案”對話方塊來開啟一個檔案,然後用記憶體對應檔來開啟該檔案,如果成功,視窗的標題條會顯示開啟的檔案的名稱,您可以通過選擇“File/Save”功能表項目來把換名儲存。該程式將會把開啟的檔案的內容存到新檔案中去。注意,這整個過程您根本就沒有用到GlobalAlloc這樣的分配記憶體的函數。

.386
.model flat,stdcall
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
.const
IDM_OPEN equ 1
IDM_SAVE equ 2
IDM_EXIT equ 3
MAXSIZE equ 260
.data
ClassName db "Win32ASMFileMappingClass",0
AppName db "Win32 ASM File Mapping Example",0
MenuName db "FirstMenu",0
ofn OPENFILENAME <>
FilterString db "All Files",0,"*.*",0
db "Text Files",0,"*.txt",0,0
buffer db MAXSIZE dup(0)
hMapFile HANDLE 0 ; Handle to the memory mapped file, must be
;initialized with 0 because we also use it as
;a flag in WM_DESTROY section too
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hFileRead HANDLE ? ; Handle to the source file
hFileWrite HANDLE ? ; Handle to the output file
hMenu HANDLE ?
pMemory DWORD ? ; pointer to the data in the source file
SizeWritten DWORD ? ; number of bytes actually written by WriteFile
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,\
ADDR AppName, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,300,200,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_CREATE
invoke GetMenu,hWnd ;Obtain the menu handle
mov hMenu,eax
mov ofn.lStructSize,SIZEOF ofn
push hWnd
pop ofn.hWndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,MAXSIZE
.ELSEIF uMsg==WM_DESTROY
.if hMapFile!=0
call CloseMapFile
.endif
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.if lParam==0
.if ax==IDM_OPEN
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile,ADDR buffer,\
GENERIC_READ ,\
0,\
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov hFileRead,eax
invoke CreateFileMapping,hFileRead,NULL,PAGE_READONLY,0,0,NULL
mov hMapFile,eax
mov eax,OFFSET buffer
movzx edx,ofn.nFileOffset
add eax,edx
invoke SetWindowText,hWnd,eax
invoke EnableMenuItem,hMenu,IDM_OPEN,MF_GRAYED
invoke EnableMenuItem,hMenu,IDM_SAVE,MF_ENABLED
.endif
.elseif ax==IDM_SAVE
mov ofn.Flags,OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetSaveFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile,ADDR buffer,\
GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_READ or FILE_SHARE_WRITE,\
NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov hFileWrite,eax
invoke MapViewOfFile,hMapFile,FILE_MAP_READ,0,0,0
mov pMemory,eax
invoke GetFileSize,hFileRead,NULL
invoke WriteFile,hFileWrite,pMemory,eax,ADDR SizeWritten,NULL
invoke UnmapViewOfFile,pMemory
call CloseMapFile
invoke CloseHandle,hFileWrite
invoke SetWindowText,hWnd,ADDR AppName
invoke EnableMenuItem,hMenu,IDM_OPEN,MF_ENABLED
invoke EnableMenuItem,hMenu,IDM_SAVE,MF_GRAYED
.endif
.else
invoke DestroyWindow, hWnd
.endif
.endif
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
CloseMapFile PROC
invoke CloseHandle,hMapFile
mov hMapFile,0
invoke CloseHandle,hFileRead
ret
CloseMapFile endp
end start

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.