windows核心编程--在应用程序中使用虚拟内存

-windows三种内存操控机制
1.虚拟内存
2.内存映射文件.
3,堆.

-预订地址空间区域
1.

// 返回预订成功的区域的基地址
PVOID VirtualAlloc(
// 内存地址。
// NULL:系统自动选择一块闲置区域。
// 传给pvAddress的地址须始终位于用户的用户模式分区中。
// 起始地址须是分配粒度整数倍。不是时,向下取整到整数倍后使用。
// 如指定(300 * 65536 + 8192),向下取整后采用(300 * 65536)
PVOID pvAddress,
// 预订区域大小
// 大小时页面尺寸整数倍。不足时,向上取整到整数倍。如62KB,取整后64KB。
SIZE_T dwSize,
// 预订时为 MEM_RESERVE
DWORD fdwAllocationType,
// 预订时指定保护属性并不是必要的
DWORD fdwProtect
);

2.如应用在非同一内存访问机器运行,可用以下来强制在某节点的物理内存中分配一部分虚拟内存。

PVOID VirtualAllocExNuma(
HANDLE hProcess,
PVOID pvAddress,
SIZE_T dwSize,
DWORD fdwAllocationType,
DWORD fdwProtect,
DWORD dwPreferredNumaNode
);

-给已预订区域调拨物理存储器
预订区域后,还需给区域调拨物理存储器,才能访问其中内存地址。
调拨时,起始地址和大小都是页面大小整数倍 。
通常调拨时,后备物理存储器都是页交换文件。

// 返回调拨成功的区域的基地址
PVOID VirtualAlloc(
// 内存地址。
// 传给pvAddress的地址须始终位于用户的用户模式分区
// 起始地址须是页面大小的整数倍。不是时,向下取整到整数倍后使用。
// 如指定(512KB + 2KB),向下取整后采用(512KB)
PVOID pvAddress,
// 预订区域大小
// 大小时页面尺寸整数倍。不足时,向上取整到整数倍。如62KB,取整后64KB。
SIZE_T dwSize,
// 调拨时为 MEM_COMMIT
DWORD fdwAllocationType,
// 调拨时指定保护属性是必要的
DWORD fdwProtect
)

-大页面支持
1.CPU支持大页面分配,即

// 返回不是0
SIZE_T GetLargePageMinimum();

2.要分配内存大于上述返回值。且要分配内存块大小是上述返回值整数倍。
3.一次进行预订+调拨时,可用。
4.限定保护属性为PAGE_READWRITE。
5.给VirtualAlloc指定MEM_LARGE_PAGE标记。

上述分配得到的内存只会驻留在内存中。即,在内存中锁定了页面。

-撤销调拨 / 释放区域

BOOL VirtualFree(
// 释放区域要求指定地址,地址须是区域的基地址
LPVOID pvAddress,
// 由于释放区域必须整块释放,所以,dwSize必须是0
SIZE_T dwSize,
// MEM_RELEASE
// 释放区域,会先撤销给区域的所有物理存储器,再释放区域。
DWORD fdwFreeType
);
BOOL VirtualFree(
// 指定一个地址,此地址所在页面被撤销调拨
LPVOID pvAddress,
// 撤销调拨的大小。
// pvAddress + dwSize所在的页面被撤销调拨。
// 两者之间的页面也被撤销调拨。
SIZE_T dwSize,
// MEM_DECOMMIT
DWORD fdwFreeType
);

-一种获取&使用对话框中空间尺寸信息方法
// 得到控件屏幕坐标
GetWindowRect(HWND hWndCtrl_, RECT*);
// 屏幕坐标转换到窗口坐标
// 这样好像避开了对话框单位。后续可用转化后尺寸信息,在对话框处理函数中响应WM_PAINT时,进行绘制。
MapWindowPoints(HWND hWndFrom_, HWND hWndTo_, LPPOINT, int);

-查询虚拟内存状态

SIZE_T WINAPI VirtualQuery(
// 地址,从此地址所在页开始。
  _In_opt_ LPCVOID                   lpAddress,
  _Out_    PMEMORY_BASIC_INFORMATION lpBuffer,
  _In_     SIZE_T                    dwLength
);

-改变保护属性

BOOL VirtualProtect(
PVOID pvAddress,
SIZE_T dwSize,
DWORD flNewProtect,
// 返回原来的保护属性
PDWORD pflOldProtect
);

-重置物理存储器的内容
重置物理存储器值的是,如果系统决定将一个内存页挪作他用,它不会将页面的内容保存到页交换文件中。
VirtualAlloc + MEM_RESET。

调拨VritualAlloc时,
1.被引用页面在页交换文件中,下次访问被引用页面时,使用新的,全部清零的内存页。
2.被引用页面在内存中,所有页面变成闲置页面。页面内容不写入到页交换文件。

和其它虚拟内存函数不同,重置时,
重置部分 < 指定的大小。基地址取整和大小取整的方式,和其它函数相反。为了放置重置调同一页面其它数据。

-地址窗口扩展
提供了一种方式,让应用可分配一块或多块内存。
应用预订地址空间区域,地址窗口。
应用调用一个函数,把一块内存指定到该地址窗口。

// 预订+指定为地址窗口扩展
// 以作为物理内存作为虚拟地址区域的后备存储器。
PVOID pvWindow = VirtualAlloc(
NULL,
ulRAMBytes,
MEM_RESERVE | MEM_PHYSICAL,
// MEM_PHYSICAL下只能用PAGE_READWRITE
PAGE_READWRITE);

// 分配物理内存,这些内存后续可被映像到进程的虚拟地址空间。
// 调用进程须具备: SeLockMemoryPrivilege 
AllocateUserPhysicalPages(
// 句柄须具备:PROCESS_VM_OPERATION权限。因为这些物理内存不会换出到页交换文件,即,内存锁定。
GetCurrentProcess(),
// 输入:页数
// 输出:实际分配的可能比要求的少
&ulRAMPages,
// 页数数元素的数组,存储页框号。数组须应用分配。
aRAMPages);

// 把 为地址窗口扩展而分配的物理地址关联到依据预订的进程虚拟地址。
MapUserPhysicalPages(
pvWindow,
ulRAMPages,
aRAMPages);

// 释放 为地址窗口扩展而分配的物理页。释放时,如存在到地址窗口的映射,会先取消映射,再释放。
FreeUserPhysicalPages(
GetCurrentProcess(),
&ulRAMPages,
aRAMPages);

-页面锁定

// 确保指定区域以内存为后备存储器。不会进行内存页和页交换文件的置换
BOOL WINAPI VirtualLock(
  _In_ LPVOID lpAddress,
  _In_ SIZE_T dwSize
);

BOOL WINAPI VirtualUnlock(
  _In_ LPVOID lpAddress,
  _In_ SIZE_T dwSize
);

你可能感兴趣的:(System-Windows)