windows内存管理方法3种: 1.虚拟内存,适合管理大型对象和数组结构。 2.内存映射文件,适合管理大型数据流以及实现在单个计算机上运行的多个进程之间共享数据。 3.内存堆,适合管理小型对象 一、分配: PVOID VirtualAlloc( PVOID pvAddress, //NULL的话由windows自动寻找起始地址(按照分配粒度 //的边界来圆整(64k),否则要给出用户方式下的地址 //(0x00010000~0x80000000)。 SIZE_T dwSize, //大小(以页为单位) DWORD fdwAllocationType, //分配方式(MEM_RESERVE,MEM_COMMIT,MEM_TOP_DOWN), //还有用于清除物理存储器内容的MEM_RESET //可以用or连接 DWORD fdwProtect); //指明该区域的保护属性 //(PAGE_NOACCESS,PAGE_READWRITE, //PAGE_READONLY,PAGE_EXECUTE, //PAGE_EXECUTE_READ,PAGE_EXECUTE_READWRITE) //但不可以出现COPYWRITE 运行失败pvAddress为NULL,否则返回起始地址。 释放: BOOL VirtualFree( LPVOID pvAddress, //也是按照页面的分配粒度(64K) SIZE_T dwSize, //大小 DWORD fdwFreeType); //方式(MEM_RELEASE,MEM_DECOMMIT) 其中MEM_DECOMMIT按页面大小(64k)释放,用MEM_RELEASE时dwsize必须为0,否则释放失败 MEM_DECOMMIT是释放物理内存,但保留虚拟内存的分配,MEM_RELEASE则是释放物理内存和虚拟内存。
二、
内存映射文件3个作用:
1、系统使用他来加载.exe和DLL文件,加快程序启动速度。
2、访问磁盘上的数据文件,相当于可以把整个硬盘看成虚拟内存。
3、在多个进程之间共享数据(windows提供的其他方法也是用它来实现的)。
分配:
1、HANDLE CreateFile(
PCSTR pszFileName, //名字
DWORD dwDesiredAccess, //访问方式(GENERIC_READ,GENERIC_WRITE, //GENERIC_READ|GENERIC_WRITE,0)
DWORD dwShareMode, //共享方式(FILE_SHARE_READ,FILE_SHARE_WRITE,
//FILE_SHARE_READ|FILE_SHARE_WRITE,0)
PSECURITY_ATTRIBUTES psa, //安全属性
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
注意:创建不成功则返回INVALID_HANDLE_VALUE((HANDLE)-1),而不是NULL。
2、HANDLE CreateFileMapping(
HANDLE hFile, //CreateFile返回的值
PSECURITY_ATTRIBUTES psa,
DWORD fdwProtect, //设定保护属性(PAGE_READONLY--对应GENERIC_READ
//(PAGE_READWRITE--对应GENERIC_READ|GENERIC_WRITE
//(PAGE_WRITECOPY-对应GENERIC_READ或GENERIC_WRITE
DWORD dwMaximumSizeHigh, //高32位
DWORD dwMaximumSizeLow, //低32位
PCTSTR pszName); //映射文件名(用于在进程之间共享),也可以是NULL
注意:创建失败是返回NULL,与CreateFile不同。当hFile=-1时是在页文件上创建映射而不是在专用硬盘上。
3、将文件数据映射到进程的地址空间,相当与提交物理存储空间
PVOID MapViewOfFile(
HANDLE hFileMappingObject, //由CreateFileMapping或OpenFileMapping返回
DWORD dwDesiredAccess, //设定数据访问方式
//(FILE_MAP_WRITE--PAGE_READWRITE,
//FILE_MAP_READ--PAGE_READONLY,PAGE_READWRITE,
//PAGE_WRITECOPY
//FILE_MAP_ALL_ACCESS--PAGE_READWRITE
//FILE_MAP_COPY--PAGE_READONLY,PAGE_READWRITE
//PAGE_WRITECOPY
DWORD dwFileOffsetHigh, //映射第一个字节的偏移量(64K的倍数)
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap); //映射大小,0的话为整个文件大小,按4k倍数来
释放:
BOOL UnmapViewOfFile(PVOID pvBaseAddress);
BOOL CloseHandle(HANDLE hObject);
理想中地调用方式:
HANDLE hFile = CreateFile(...);
HANDLE hFileMapping = CreateFileMapping(hFile,...);
PVOID pvFile = MapViewOfFile(hFileMapping,...);
//using...
UnmapViewOfFile(pvFile);
CloseHandle(hFileMapping);
CloseHandle(hFile);
!!下面的书上说不会出错,我试了一下,出错了!还是用上面的方法吧
或者更好的:
HANDLE hFile = CreateFile(...);
CloseHandle(hFile);
HANDLE hFileMapping = CreateFileMapping(hFile,...);
CloseHandle(hFileMapping);
PVOID pvFile = MapViewOfFile(hFileMapping,...);
UnmapViewOfFile(pvFile);