windows内存模型       

windows内存模型

系统调拨物理存储器(磁盘中的页交换文件和文件映像)给进程的数据与程序,把地址映射到进程地址空间。
一开始进程所有页面都在磁盘上,内存中没有数据与程序,所以要先从它们的物理存储器中调入内存。

进程虚拟地址空间

虚拟内存

让磁盘空间看起来像内存一样,这部分磁盘空间称为页交换文件。
页交换文件在硬盘上,一种内存的后备存储器。把页交换文件映射到进程地址空间。

使用虚拟内存

1.预定地址空间区域

PVOID VirtualAlloc(
	PVOID pvAddress,
	SIZE_T dwSize,
	DWORD fdwAllocationType,
	DWORD fdwProtect); fdwAllocationType设置为MEM_RESERVE	

2.调拨物理存储器(页交换文件)
fdwAllocationType设置为MEM_COMMIT 3.撤销调拨物理存储器及释放区域

BOOL VirtualFree(
	LPVOID pvAddress,
	SIZE_T dwSize,
	DWORD fdwFreeType);

线程栈

系统创建线程时,会给线程栈预订一块地址空间区域,并调拨页交换文件(大小由.exe的PE文件头中变量指定)。

内存映射文件

文件映像(.exe文件或DLL),另一种后备存储器,称之为内存映射文件,映射到进程地址空间。
硬盘上的文件映射在进程的地址空间中。 1.创建或打开文件,创建文件内核对象

HANDLE CreateFile(
	PCSTR pszFileName,
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	PSECURITY_ATTRIBUTES psa,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile); 2.创建内存映射文件内核对象   

HANDLE CreateFileMapping(
	HANDLE hFile,
	PSECURITY_ATTRIBUTES psa,
	DWORD fdwProtect,
	DWORD dwMaximumSizeHigh,
	DWORD dwMaximumSizeLow,
	PCTSTR pszName);

3.映射到进程地址空间,在地址空间中预订区域并调拨物理存储器

PVOID MapViewOfFile(
	HANDLE hFileMappingObject,
	DWORD dwDesiredAccess,
	DWORD dwFileOffSetHigh,
	DWORD dwFileOffSetLow,
	SIZE_T dwNumberOfBytesToMap);

用应用程序的共享段实现多个实例间的共享静态数据

告诉编译器把变量放入单独的段中

#pragma data_seg("shared")
#pragma data_set()
#pragma comment(linker, "/SECTION:Shared,RWS")

####用内存映射文件在进程间共享数据 当启动一个应用程序,系统会先调用CreateFile打开.exe文件,接着调用CreateFileMapping创建文件映射对象,最后调用MapViewOfFileEx映射到进程的固定地址空间(有.exe的PE文件指定基地址)。打开同一个应用程序,系统发现已经存在文件映射对象,就调用MapViewOfFileEx映射.exe文件到对应进程的地址空间。所以系统把相同文件映射到不同进程中,令进程共享程序的代码与数据。
####以页交换文件为后备存储器的内存映射文件 不再以磁盘文件作为后备存储器,则不需要打开文件创建文件内核对象,直接创建内存映射文件对象,把页交换文件映射到内存。
多进程可以利用页交换文件的内存映射文件来共享数据。利用对映射文件对象取别名来标记对象。
###堆 进程创建的时候,系统会分配一个默认堆。 调拨的物理存储器来自页交换文件。
####创建额外堆 HeapCreate( DWORD fdwOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize); 不能保证线程独占堆则不能设置fdwOptions为HEAP_NO_SERIALIZE,保证多线程对同一个堆的访问时依次进行。 ####从堆中分配内存 PVOID HeapAlloc( HANDLE hHeap, DWORD fdwFlags, SIZE_T dwBytes);