第四章到第九章講了一些UI的操作,還有時間及繪圖,最近一直在研究寫一個文本編輯器就好久沒發文章了,編輯器也快寫完了,之後還準備寫個檔案搜尋器,練習資料庫和多線程。
第十章是檔案操作和記憶體管理,寫文本編輯器也就用到這暫時,現在把這一章的筆記貼出來。我發現儲存成rtf格式,在代碼片中,所有的縮進就都正常了。
10
10.1.1
--------标準記憶體管理函數- |-------------------------
----堆管理函數-----------|---記憶體映射檔案函數---
虛拟記憶體管理函數--------- |-------------------------
------------------Windows記憶體管理器-----------------
---------------實體記憶體-------交換檔案-------------
虛拟記憶體管理函數:保留送出釋放虛拟記憶體
堆管理函數:操作所有的預設堆和裡面的私有堆
标準記憶體管理函數:在預設堆内配置設定和釋放記憶體
記憶體映射檔案函數:把檔案映射到記憶體後,在記憶體中讀寫檔案
10.1.2
一個程序4GB,高2GB給系統核心使用,低2GB自己用
申請記憶體前,需要知道現在記憶體的配置設定情況
invoke GlobalMemoryStatus, lpBuffer
lpBuffer: MEMORYSTATUS
dwLength dw ? ;本結構長度
dwMemoryLod dw ? ;已用記憶體百分比
dwTotalPhys dw ? ;實體記憶體總量
dwAvailPhys dw ? ;可用實體記憶體
...
調用前先填寫dwLength,調用成功後,函數在結構中傳回對應的數值
10.1.3
标準記憶體管理函數(預設堆中)
GlobalAlloc
GlobalFree
GlobalReAlloc
GlobalLock
GlobalUnlock
GlobalDiscard
GlobalFlags
GlobalHandle
GlobalSize
固定的記憶體塊
//申請
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINT, dwSizeInByte
//申請成功傳回記憶體指針,不成功傳回NULL
.if eax
mov lpMemory, eax
.endif
//釋放
invoke GlobalFree, lpMemory
//釋放成功傳回NULL,不成功傳回lpMemory
//手動釋放防止記憶體洩漏,程式結束後系統自動釋放
//修改大小
invoke GlobalReAlloc, lpMemory, dwSizeInByte, GMEM_ZEROINT or GMEM_MOVABLE
//申請成功傳回記憶體指針,不成功傳回NULL
//原空間已有資料會複制到新空間
.if eax
mov lpMemory, eax
.endif
可移動的記憶體塊(消除碎片化)
//申請
invoke GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINT, dwSizeInByte
.if eax
mov hMemory, eax
//使用之前先鎖定,Windows不會移動它
invoke GlobalLock, hMemory
.if eax
mov lpMemory, eax
.endif
//暫時不用,可以解鎖
invoke GlobalUnlock, hMemory
//鎖定和解鎖配對使用才行
//釋放(不論是否鎖定)
invoek GlobalFree, hMemory
//修改大小
invoke GlobalReAlloc, hMemory, dwSizeInByte, GMEM_ZEROINT or GMEM_MOVEABLE
//修改大小前先解鎖!
可丢棄的記憶體塊
//申請
invoke GlobalAlloc, GHND or GMEM_DISCARDABLE
.if eax
mov hMemory, eax
.endif
//記憶體塊被丢棄時資料丢失,無法鎖定,但是可以重新配置設定
//記憶體塊處于非鎖定狀态,可以手動丢棄
invoke GlobalDiscard, hMemory
//鎖定和解鎖和釋放和修改大小同可移動的記憶體塊
擷取記憶體塊資訊
//擷取鎖定計數,是否被丢棄
invoke GlobalFlags, hMemory
//GMEM_INVALID_HANDLE:調用失敗
//低8位代表鎖定計數
//擷取記憶體塊句柄
invoke GlobalHandle, lpMemory
//擷取記憶體塊大小
invoke GlobalSize, hMemory
10.1.4
堆管理函數
在預設堆(同步)中的私有堆配置設定記憶體(可建立多個),實作多線程,提高效率
利于實作子產品的記憶體封裝,提高穩定性
//建立私有堆
invoke HeapCreate, uFlags, dwInitSize, dwMaxSize
.if eax && (eax < 0c00000000h)
mov hHeap, eax
.endif
//釋放私有堆
invoke HeapDestroy, hHeap
//在私有堆中配置設定記憶體(隻能配置設定固定的記憶體塊)
invoke HeapAlloc, hHeap, HEAP_ZERO_MEMORY, dwSizeInByte
.if eax && (eax < 0c0000000h)
mov lpMemory, eax
.endif
//有關獨占性和是否傳回錯誤碼的問題
//釋放記憶體
invoke HeapFree, hHeap, dwFlags, lpMemory
//重新調整大小
invoke HeapReAlloc, hHeap, dwFlags, lpMemory, dwSizeInByte
.if eax && (eax < 0c0000000h)
mov lpMemory,eax
.endif
10.1.5
虛拟記憶體管理函數
程序中的每個位址:
送出狀态(占用狀态):線程位址已經映射到實際的實體記憶體中
自由狀态:沒有映射,程式會用,還沒被使用
保留狀态:沒有映射,程式不會用,将來可能會用
保留和釋放位址空間
invoke VirtualAlloc, lpAddress, dwSize, flAllocationType, flProtect
invoke VirtualFree, lpAddress, 0, MEM_RELEASE
記憶體頁的保護和鎖定
invoke VirtualProtect, lpAddress, dwSize, flNewProtect, lpflOldProtect
invoke VirtualLock, lpAddress, dwSize
invoke VirtualUnlock, lpAddress, dwSize
10.1.6
其他記憶體管理函數
移動記憶體
invoke RtlMoveMemory, offset szDest, offset szSource, dwSize
填充記憶體塊
invoke RtlFileMemory, offset szDest, dwSize, dbFill
用0填充
invoke RtlZeroMemory, offset szDest, dwSize
記憶體狀态檢測
invoke IsBadCodePtr, lpMemory ;指針指向的單位元組是否可讀
invoke IsBadReadPtr, lpMemory, dwSize ;某段記憶體是否可讀
invoke IsBadWritePre, lpMemory, dwSize ;某段記憶體是否可寫
invoke IsBadStringPre, lpMemory, dwSize ;字元串是否可讀
10
10.2.1
檔案句柄和讀寫指針
10.2.2
打開/建立檔案
HANDLE CreateFile(//傳回一個檔案句柄
LPCTSTR lpFileName,//全路徑檔案名
DWORD dwDesiredAccess,//GENERIC_READ or GENERIC_WRITE
DWORD dwShareMode,//FILE_SHARE_READ or FILE_SHARE_WRITE
LPSECURITY_ATTRIBUTES lpSecurityAttributes,//NULL
DWORD dwCreationDisposition,//CREATE_NEW/CREATE_ALWAYS/OPEN_EXISTING/OPEN_ALWAYS
DWORD dwFlagsAndAttributes,//FILE_ATTRIBUTE_NORMAL
HANDLE hTemplateFile//NULL
);
關閉檔案
BOOL CloseHandle(HANDLE hObject);
移動檔案指針
DWORD SetFilePointer(
HANDLE hFile,//檔案句柄
LONG lDistanceToMove,//移動距離低32位,有符号
PLONG lpDistanceToMoveHigh,//移動距離高32位,一般NULL
DWORD dwMoveMethod//FILE_BEGIN/FILE_CURRENT/FIEL_END(移動距離為負)
);
擷取目前檔案指針
invoke SetFilePointer, hFile, 0, NULL, FILE_CURRENT
設定檔案結尾
invoke SetEndOfFile, hFile//把目前指針設定為檔案結尾
//若目前指針超出原檔案傳回,不報錯,檔案變長, 可以用來建立空檔案
讀/寫檔案
invoke ReadFile, hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped(異步讀寫用,一般NULl)
invoke WriteFile, hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped(異步讀寫用,一般NULl)
清空資料緩沖區并寫入
invoke FlushFileBuffers, hFile
加鎖/解鎖檔案防其他程序對該區域讀寫
invoke LockFile, hFile, dwFileOffsetLow, dwFileOffsetHign, nNumberOfBytesToLockLow, nNumberOfBytesToLockHign
invoke UnlockFile, hFile, dwFileOffsetLow, dwFileOffsetHign, nNumberOfBytesToLockLow, nNumberOfBytesToLockHign
10.2.3
查找檔案(編寫防毒軟體等)
涉及到多線程,略,準備單獨寫一個檔案搜尋器
10.2.4
檔案屬性
擷取檔案類型
invoke GetFileType, hFile
return FILE_TYPE_UNKNOWN, FILE_TYPE_DISK, FILE_TYPE_CHAR, FILE_TYPE_PIPE
未知 磁盤檔案 字元裝置 管道
擷取檔案長度
invoke GetFileSize, hFile, lpFileSizeHigh//NULL
return 長度的低32位
擷取檔案日期
invoke GetFileTime, hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime//FILETIME
invoke FileTimeToSystemTime, lpFileTime, lpSystemTime//SYSTEMTIME
設定檔案日期
invoke SystemTimeToFileTime, lpSystemTime, lpFileTime
invoke SetFileTime, hFile, lpCreationTime, lpLastAccessTime, lpLastAccessTime
擷取檔案屬性
invoke GetFileAttrubutes, lpFileAllPathName
設定檔案屬性
invoke SetFileAttrubutes, lpFileAllPathName, dwFileAttributes//與CreateFile中的參數同
10.2.5
拷貝檔案
invoke CopyFile, lpExistingFileName, lpNewFileName, bFailIfExists//檔案存在是,FALSE覆寫,TRUE失敗
CopyFileEx//提供回調函數,如顯示進度條,拷貝大型檔案有用
移動檔案
invoke MoveFile, lpExistingFileName, lpNewFileName//目标檔案名必須不存在
MoveFileEx//提供一個dwFlags參數,略
删除檔案
invoke DeleteFile, lpFileName//檔案必須關閉
10
10.3
每個邏輯驅動器的标号叫“卷标”
每個邏輯驅動器中的檔案按樹型存儲
10.3.1
卷标操作
修改卷标
szPath db 'c:\', 0 ;\反斜杠不能省略
szVolume db 'NewName', 0
invoke SetVolumeLabel, addr szPath, addr szVolume
删除卷标
invoke SetVolumeLabel, addr szPath, NULL
擷取卷标
invoke GetLogicalDrives
invoke GetLogicalDriveStrings, dwBufferSize, lpBuffer
擷取邏輯驅動器或光驅參數
invoke GetDriveType, addr szPath
GetVolumInformation可以擷取更多資訊
10.3.2
目錄操作
建立和删除目錄
szDir db 'c:\dir\2', 0 ;上級目錄必須存在且子目錄不存在
invoke CreateDirectory, addr szDir, NULL
invoke RemoveDirectory, addr szDir ;目錄必須為空才能删除
擷取特殊目錄
invoke GetCurrentDirectory, dwBufferSize, lpBuffer ;擷取目前目錄
invoke GetTempPath, dwBufferSize, lpBuffer ;擷取臨時目錄
invoke GetWindwosDirectory, lpBuffer, dwBufferSize ;擷取Windows目錄,System32
invoke GetSystemDirectory, lpBuffer, dwBufferSize ;擷取系統目錄
invoke SetCurrentDirectory, addr szDir
10.4
記憶體映射檔案(解決緩沖區邊界判斷問題,記憶體洩漏)
CreateFileMapping, OpenFileMapping, MapViewOfFile, UnmapViewOfFile, FlushViewOfFile