NtAllocateVirtualMemory 函数 (ntifs.h)
NtAllocateVirtualMemory 例程在指定进程的用户模式虚拟地址空间中保留和/或提交页面区域。
语法
__kernel_entry NTSYSCALLAPI NTSTATUS NtAllocateVirtualMemory(
[in] HANDLE ProcessHandle,
[in, out] PVOID *BaseAddress,
[in] ULONG_PTR ZeroBits,
[in, out] PSIZE_T RegionSize,
[in] ULONG AllocationType,
[in] ULONG Protect
);
参数
[in] ProcessHandle
应为其执行映射的过程的句柄。 使用 Ntddk.h 中定义的 NtCurrentProcess 宏指定当前进程。
[in, out] BaseAddress
指向将接收已分配页区域的基址的变量的指针。 如果 BaseAddress 的初始值为非 NULL,则从指定的虚拟地址开始分配区域,并向下舍入到下一个主机页大小地址边界。 如果 BaseAddress 的初始值为 NULL,则操作系统将确定区域分配位置。
[in] ZeroBits
节视图基址中必须为零的高序地址位数。 仅在操作系统确定分配区域的位置时使用,例如 BaseAddress* 为 NULL 时。 请注意,当 ZeroBits 大于 32 时,它将成为位掩码。
[in, out] RegionSize
指向变量的指针,该变量将接收已分配页区域的实际大小(以字节为单位)。 RegionSize 的初始值指定区域的大小(以字节为单位),并向上舍入到下一个主机页大小边界。 输入时,RegionSize 不能为零。
[in] AllocationType
一个位掩码,其中包含指定要为指定页面区域执行的分配类型的标志。 下表描述了最常见的标志。 有关可能标志和说明的完整列表,请参阅 VirtualAlloc 。
注意
必须设置MEM_COMMIT、MEM_RESET或MEM_RESERVE之一。
标志 | 含义 |
---|---|
MEM_COMMIT | 要提交页面的指定区域。 |
MEM_RESERVE | 将保留指定的页面区域。 |
MEM_RESET | 重置指定区域的状态,以便如果页面位于分页文件中,则将其丢弃并引入零页。 如果页面位于内存中并已修改,则它们将被标记为“未修改”,因此不会将其写出到分页文件中。 内容 不 归零。 未使用 Protect 参数,但必须将其设置为有效值。 如果设置了MEM_RESET,则不能设置任何其他标志。 |
其他 MEM_XXX 标志 | 请参阅 VirtualAlloc。 |
[in] Protect
包含页面保护标志的位掩码,这些标志指定对已提交页面区域所需的保护。 下表介绍了这些标志。
标志 | 含义 |
---|---|
PAGE_NOACCESS | 不允许访问已提交的页面区域。 尝试读取、写入或执行已提交区域会导致访问冲突异常,称为常规保护 (GP) 错误。 |
PAGE_READONLY | 允许对已提交页面区域进行只读和执行访问。 尝试写入已提交区域会导致访问冲突。 |
PAGE_READWRITE | 允许读取、写入和执行对已提交页面区域的访问权限。 如果允许对基础节进行写入访问,则共享页面的单个副本。 否则,页面在写入时共享为只读/复制。 |
PAGE_EXECUTE | 允许执行对已提交页面区域的访问。 尝试读取或写入已提交区域会导致访问冲突。 |
PAGE_EXECUTE_READ | 允许对已提交页面区域执行和读取访问权限。 尝试写入已提交区域会导致访问冲突。 |
PAGE_GUARD | 区域中的页面将成为防护页。 任何从保护页读取或写入保护页的尝试都会导致系统引发STATUS_GUARD_PAGE异常。 因此,保护页面充当一次性访问警报。 此标志是页面保护修饰符,仅当与PAGE_NOACCESS以外的某个页面保护标志一起使用时有效。 当访问尝试导致系统关闭保护页面状态时,基础页面保护将接管。 如果在系统服务期间发生保护页异常,该服务通常会返回失败状态指示器。 |
PAGE_NOCACHE | 页面区域应分配为不可缓存。 部分不允许PAGE_NOCACHE。 |
PAGE_WRITECOMBINE | 启用写入组合,即将缓存中的写入合并到硬件支持main内存。 此标志主要用于帧缓冲区内存,以便在写入设备之前,尽可能合并对同一缓存行的写入。 这可以大大减少总线上的写入,以 (例如) 视频内存。 如果硬件不支持写入组合,则忽略 标志。 此标志是页面保护修饰符,仅当与PAGE_NOACCESS以外的某个页面保护标志一起使用时有效。 |
返回值
NtAllocateVirtualMemory 返回STATUS_SUCCESS或错误状态代码。 可能的错误状态代码包括:
- STATUS_ACCESS_DENIED
- STATUS_ALREADY_COMMITTED
- STATUS_COMMITMENT_LIMIT
- STATUS_CONFLICTING_ADDRESSES
- STATUS_INSUFFICIENT_RESOURCES
- STATUS_INVALID_HANDLE
- STATUS_INVALID_PAGE_PROTECTION
- STATUS_NO_MEMORY
- STATUS_OBJECT_TYPE_MISMATCH
- STATUS_PROCESS_IS_TERMINATING
注解
NtAllocateVirtualMemory 可以执行以下操作:
- 提交先前调用 NtAllocateVirtualMemory 保留的页面区域。
- 保留一个免费页面区域。
- 保留并提交一个免费页面区域。
内核模式驱动程序可以使用 NtAllocateVirtualMemory 在指定进程中保留应用程序可访问的虚拟地址范围,然后对 NtAllocateVirtualMemory 进行其他调用,以提交保留范围内的各个页面。 这使进程能够保留其虚拟地址空间的范围,而无需使用物理存储,直到需要为止。
进程的虚拟地址空间中的每个页面都处于下表中所述的三种状态之一。
状态 | 含义 |
---|---|
FREE | 页面未提交或保留,并且进程无法访问。 NtAllocateVirtualMemory 可以保留或同时保留并提交一个免费页面。 |
RESERVED | 地址范围不能由其他分配函数使用,但进程无法访问该页,并且没有与之关联的物理存储。 NtAllocateVirtualMemory 可以提交保留页,但它不能再次保留它。 NtFreeVirtualMemory 可以释放保留页,使其成为免费页面。 |
承诺 | 为页面分配物理存储,访问由保护代码控制。 仅在首次尝试读取或写入该页时,系统才会初始化每个提交的页面并将其加载到物理内存中。 当进程终止时,系统将释放已提交页面的存储。 NtAllocateVirtualMemory 可以提交已提交的页面。 这意味着你可以提交一系列页面,不管它们是否已提交,并且函数不会失败。 NtFreeVirtualMemory 可以取消提交已提交页面、释放页面的存储,也可以同时取消提交和释放已提交页面。 |
通过调用 NtAllocateVirtualMemory 分配的内存必须通过调用 NtFreeVirtualMemory 来释放。
有关内存管理的详细信息,请参阅 Windows 驱动程序的内存管理。
注意 如果在用户模式下调用 NtAllocateVirtualMemory 函数,则应使用名称“NtAllocateVirtualMemory”而不是“ZwAllocateVirtualMemory”。
对于来自内核模式驱动程序的调用,Windows Native System Services 例程的 NtXxx 和 ZwXxx 版本在处理和解释输入参数的方式上的行为可能有所不同。 有关例程的 NtXxx 和 ZwXxx 版本之间的关系的详细信息,请参阅 使用本机系统服务例程的 Nt 和 Zw 版本。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 2000 |
目标平台 | 通用 |
标头 | ntifs.h (包括 Ntifs.h) |
Library | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | PASSIVE_LEVEL |
DDI 符合性规则 | HwStorPortProhibitedDDI、PowerIrpDDis、SpNoWait、StorPortStartIo |