pub fn virtual_alloc_ex(
h_process: HANDLE,
address: Option<*const c_void>,
size: usize,
allocation_type: VIRTUAL_ALLOCATION_TYPE,
protect: PAGE_PROTECTION_FLAGS,
) -> *mut c_voidExpand description
保留、提交或更改指定进程的虚拟地址空间中内存区域的状态。 函数将它分配的内存初始化为零。
若要指定物理内存的 NUMA 节点,请参阅 virtual_alloc_ex_numa。
每个页面都有一个关联的 页面状态。 virtual_alloc_ex 函数可以执行以下操作:
• 提交保留页的区域
• 保留免费页面区域
• 同时保留和提交可用页面区域
virtual_alloc_ex 无法保留保留页。 它可以提交已提交的页面。 这意味着你可以提交一系列页面,无论它们是否已提交,并且函数不会失败。
可以使用 virtual_alloc_ex 保留页块,然后对 virtual_alloc_ex 进行其他调用,以提交保留块中的单个页面。 这使进程能够保留其虚拟地址空间的范围,而无需使用物理存储,直到需要为止。
如果 address 参数不为 NULL,则该函数使用 address 和 size 参数来计算要分配的页面区域。 整个页面范围的当前状态必须与 allocation_type 参数指定的分配类型兼容。 否则,函数将失败,并且不会分配任何页。 此兼容性要求不排除提交已提交的页面;请参阅前面的列表。
若要执行动态生成的代码,请使用 virtual_alloc_ex 分配内存,并使用 virtual_protect_ex 函数授予 PAGE_EXECUTE 访问权限。
virtual_alloc_ex函数可用于在指定进程的虚拟地址空间中保留地址窗口扩展(AWE)内存区域。然后,可以使用此内存区域根据应用程序的要求将物理页映射到虚拟内存中和映射出虚拟内存。必须在allocation_type参数中设置MEM_PHYSICAL和MEM_RESERVE值。不得设置MEM_COMMIT值。
页面保护必须设置为PAGE_READWRITE。virtual_free_ex 函数可以取消提交已提交页面、释放页面的存储,也可以同时取消提交和释放已提交页面。 它还可以释放保留页,使其成为免费页面。
创建可执行的区域时,调用程序负责在代码设置到位后,通过适当调用 flush_instruction_cache 来确保缓存一致性。 否则,尝试在新可执行区域之外执行代码可能会产生不可预知的结果。
h_process 进程的句柄。 函数在此进程的虚拟地址空间中分配内存。句柄必须具有 PROCESS_VM_OPERATION 访问权限。 有关详细信息,请参阅 进程安全和访问权限。
address 为要分配的页面区域指定所需起始地址的指针。如果要保留内存,该函数将此地址向下舍入到分配粒度的最接近倍数。如果要提交已保留的内存,该函数会将此地址向下舍入到最近的页边界。若要确定主计算机上的页面大小和分配粒度,请使用get_system_info函数。如果address为NULL,则该函数确定分配区域的位置。如果此地址位于尚未通过调用initialize_enclave进行初始化的enclave内,virtual_alloc_ex会为该地址上的enclave分配一个零页。该页面必须以前未提交,并且不会使用IntelSoftwareGuardExtensions编程模型的EEXTEND指令进行测量。如果中的地址位于你初始化的enclave中,则分配操作将失败并出现ERROR_INVALID_ADDRESS错误。对于不支持动态内存管理的enclave((即SGX1))也是如此。SGX2enclave将允许分配,并且页面必须在分配后被enclave接受。
size 要分配的内存区域的大小(以字节为单位)。如果address为NULL,则该函数会将size向上舍入到下一页边界。如果address不为NULL,则该函数将分配从address到address+size范围内包含一个或多个字节的所有页。例如,这意味着跨越页边界的2字节范围会导致函数分配这两个页面。
allocation_type 内存分配的类型。 此参数必须包含以下值之一。
- MEM_COMMIT 从指定保留内存页的磁盘) 上的总内存大小和分页文件 (分配内存费用。 函数还保证当调用方稍后最初访问内存时,内容将为零。 除非实际访问虚拟地址,否则不会分配实际物理页。若要在一个步骤中保留和提交页面,请使用 调用 virtual_alloc_ex MEM_COMMIT | MEM_RESERVE。除非已保留整个范围,否则尝试通过指定 MEM_COMMIT 而不 指定MEM_RESERVE 和非 NULL address 来提交特定地址范围。 生成的错误代码 ERROR_INVALID_ADDRESS。尝试提交已提交的页面不会导致函数失败。 这意味着可以提交页面,而无需首先确定每个页面的当前承诺状态。如果 address 指定 enclave 中的地址,则必须MEM_COMMIT allocation_type。
- MEM_RESERVE 保留进程的虚拟地址空间范围,而无需在内存或磁盘上的分页文件中分配任何实际物理存储。通过使用 MEM_COMMIT 再次调用 virtual_alloc_ex 来提交保留页。 若要在一个步骤中保留和提交页面,请使用 调用 virtual_alloc_ex MEM_COMMIT | MEM_RESERVE。其他内存分配函数(如 malloc 和 local_alloc)在释放内存之前无法使用保留内存。
- MEM_RESET 指示 address 和 size 指定的内存范围中的数据不再感兴趣。 不应从分页文件读取或写入页面。 但是,内存块稍后将再次使用,因此不应解除提交。 此值不能与任何其他值一起使用。使用此值并不能保证使用 MEM_RESET 操作的范围将包含零。 如果希望范围包含零,请取消提交内存,然后重新提交。使用 MEM_RESET 时, virtual_alloc_ex 函数将忽略protect 的值。 但是,仍必须将 protect 设置为有效地保护值,例如 PAGE_NOACCESS。如果使用 MEM_RESET 并且内存范围映射到文件,则 virtual_alloc_ex 将返回错误。 仅当共享视图映射到分页文件时,才可接受该视图。
- MEM_RESET_UNDO 应仅对之前成功应用MEM_RESET的地址范围调用MEM_RESET_UNDO。 它指示调用方对 address 和 size 指定的指定内存范围中的数据感兴趣,并尝试反转 MEM_RESET的影响。 如果该函数成功,则表示指定地址范围中的所有数据都保持不变。 如果函数失败,则地址范围中至少有一些数据已替换为零。此值不能与任何其他值一起使用。 如果 对 之前未MEM_RESET的地址范围调用 MEM_RESET_UNDO ,则行为未定义。 指定 MEM_RESET时, virtual_alloc_ex 函数将忽略 protect 的值。 但是,仍必须将 protect 设置为有效地保护值,例如 PAGE_NOACCESS。Windows Server 2008 R2、Windows 7、Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP: 在Windows 8和Windows Server 2012之前,不支持MEM_RESET_UNDO标志。 此参数还可以按指示指定以下值。
- MEM_LARGE_PAGES 使用 大页支持分配内存。大小和对齐方式必须是大页最小值的倍数。 若要获取此值,请使用 get_large_page_minimum 函数。如果指定此值,还必须指定 MEM_RESERVE 和 MEM_COMMIT。
- MEM_PHYSICAL 保留可用于映射 地址窗口扩展 (AWE) 页的地址范围。此值必须与 MEM_RESERVE 一起使用,不能与其他值一起使用。
- MEM_TOP_DOWN 在可能的最高地址分配内存。 这比常规分配慢,尤其是在有许多分配时。
protect要分配的页区域的内存保护。 如果正在提交页面,则可以指定任何一个 内存保护常量。如果 address 指定 enclave 中的地址, 则 protect 不能为以下任何值: • PAGE_NOACCESS • PAGE_GUARD • PAGE_NOCACHE • PAGE_WRITECOMBINE 为 enclave 分配动态内存时, protect 参数必须 PAGE_READWRITE 或 PAGE_EXECUTE_READWRITE。