Windows系统编程 chap5
Windows系统编程 chap5
内存管理,内存映射文件和DLL
内存映射文件把进程地址空间跟文件直接关联,允许操作系统管理在文件和内存之间的所有的数据移动,从而程序员不需要处理ReadFile,WriteFile,SetFilePointer或其它I/O函数。有了内存映射文件,可以方便程序维护永久文件中的动态数据结构,且基于内存的算法可以处理文件数据。而且,内存映射将大大加快顺序文件和处理速度,并能提供在进程之间内存共享的机制。
DLL是文件映射和共享内存的特例,此时文件(主要是只读代码文件)被映射到进程地址空间以执行。
5.1 Win32和Win64内存管理架构
“32位”在内存地址本身就可以体现,指针(LPCTSTR, LPDWORD等等)是4字节(32位)对象。
每个Win32进程具有自己4GB长的私有虚拟地址空间。Win32中至少有一半(2-3GB,3GB在启动时必须打开)地址用于进程。虚拟地址空间的剩余部分分配给共享数据和代码,系统代码,驱动器等等。
操作系统管理虚拟内存到物理内存映射,页面交换,页面调度等。 《Inside Windows 2000》
。系统具有相对较少的物理内存
。每个进程具有自己的虚拟地址空间
。操作系统映射虚拟地址到物理地址
。许多虚拟页面将不在物理内存中,因此操作系统响应页面错误(引用的页面不在内存中),并从硬盘上的系统交换文件或普通文件中加载数据。
VOID GetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
5.2 堆
Windows以堆的方式来维护内存池。一个进程可以包含多个堆,可以从这些堆中分配内存。
如果单个堆足够了,就使用C库内存管理函数(malloc, free, calloc, realloc)
堆是Windows对象。因此,它们具有句柄。当分配内存时堆句柄是必需的。每个进程具有自己的缺省堆,它被malloc使用,而下一个函数获得其句柄。
HANDLE GetProcessHeap(VOID)
不同堆的优点如下:
。公开
。多线程性能
。分配效率
。解除分配效率
。引用局部化的效率
5.3 管理堆内存
通过指定堆句柄,块大小和几个标记来从堆中获得内存块。
LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes)
通过堆句柄和块指针来调用HeapSize(该函数应该命名为BlockSize因为它不包含堆的大小)以决定分配块的大小。
DWORD HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
5.3.1 HEAP_NO_SERIALIZE标记
使用该标记会有较小的性能提升,因为该函数跟访问堆的线程没有相互排斥。
5.3.2 HEAP_GENERATE_EXCEPTIONS标记
5.3.3 其它堆函数
HeapCompact试图整理堆中邻近空闲块的碎片。
HeapValidate检测堆的出错。
HeapWalk列举堆里的块
5.3.4 小结:堆管理
1).使用CreateHeap或者GetProcessHeap来获取一个堆句柄
2). 使用HeapAlloc在堆内分配块
3).
5.4 范例:使用
5.5 内存映射文件
5.5.1 文件映射对象
5.5.2 映射进程地址空间到映射对象
分配虚拟内存空间并通过映射对象映射到文件。分配的块映射到用户指定的文件中,而不是页面调度文件中。
LPVOID MapViewOfFile()
5.5.3 文件映射的限制
5.5.4 小结:文件映射
- 打开文件,确保它具有GENERIC_READ访问权限
- 文件是新建的,需要通过CreateFileMapping或者使用SetFilePointer和SetEndOfFile来设置文件长度
- 使用CreateFileMapping或OpenFileMapping来映射文件
- 使用MapViewOfFile创建一个或多个视图
- 通过内存引用来访问文件
- 在结束时,依次对映射句柄执行UnmapViewOfFile,CloseHandle,对文件句柄执行CloseHandle
5.6 范例:对映射文件进行顺序文件处理
5.7 排序内存映射文件
5.8 范例:使用基准指针
5.9 动态链接库
DLL是文件映射最明显和重要的应用。DLL对于高级技术比如COM来说是必需的
5.9.1 静态和动态库
单映像模式缺点:
5.9.2 隐式链接
5.9.3 导出和导入接口
5.9.4 显式链接
5.10
5.11 DLL入口点
BOOL DllMain(HINSTANCE hDll, DWORD Reason, LPVOID Reserved)
5.12 DLL版本管理
HRESULT CALLBACK DllGetVersion(DLLVERSIONINFO *pdvi)
5.13 总结