Windows 64位可以在7FFF'FFFF'FFFF上分配虚拟内存吗?

问题描述 投票:1回答:3

上下文

我正在努力升级.NET库以支持64位。该库直接在Windows上的其他进程的内存中执行各种操作。我必须选择两种类型IntPtr(最大正值7FFF'FFFF'FFFF'FFFF)或UIntPtr(最大正值FFFF'FFFF'FFFF'FFFF)来处理我的内存指针。网上有很多关于这两者的信息。 IntPtr似乎是事实上同意的选择,因为它符合CLS并且大多数.NET API依赖于它(来自Marshal的ref InteropServices)。

这个问题

我决定打开一个64位进程并检查分配的内存区域,以及进程中加载​​的模块,看看使用UIntPtr(地址> 7FFF'FFFF'FFFF'FFFF)支持无符号指针是否有价值。如下面的屏幕截图所示,似乎内存地址不加载符号,也不分配超过7FFF'FFFF'FFFF的内存。有这样做的具体原因吗?在某些情况下,Windows是否可以在该值上分配内存区域?

谢谢 !

Memory allocation on Cheat Engine (64-bit)

c# windows memory 64bit internals
3个回答
1
投票

在Windows中,每个进程只有8TB的地址空间,因此用户代码的上限是0x7FF'FFFF'FFFF

进程可用的虚拟地址范围称为进程的虚拟地址空间。每个用户模式进程都有自己的私有虚拟地址空间。对于32位进程,虚拟地址空间通常为2千兆字节范围0x00000000到0x7FFFFFFF。对于64位进程,虚拟地址空间为8TB范围0x000'00000000到0x7FF'FFFFFFFF。一系列虚拟地址有时称为一系列虚拟内存。

此图说明了虚拟地址空间的一些主要功能。

some of the key features of virtual address spaces

https://docs.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/virtual-address-spaces

上层248TB属于内核模式,总计高达256TB的地址空间,由48位寻址。这意味着可能的最高正地址是247-1 = 0x7FFF'FFFF'FFFF

在64位Windows中,理论上的虚拟地址空间量为2 ^ 64字节(16艾字节),但实际上只使用了16-exabyte范围的一小部分。从0x000'00000000到0x7FF'FFFFFFFF的8TB范围用于用户空间,并且从0xFFFF0800'00000000到0xFFFFFFFF'FFFFFFFF的248TB的部分用于系统空间。

重要的部分是48位宽,可能是因为大多数当前的x86-64实现使用48位虚拟地址

AMD64架构的最初实现实现了40位物理地址,因此可以处理高达1 TB(240字节)的RAM。 AMD64架构的当前实现(从AMD 10h微体系结构开始)将其扩展到48位物理地址,因此可以处理高达256 TB的RAM。该体系结构允许将其扩展到52位(受页表格式限制);这将允许寻址高达4 PB的RAM。

https://en.wikipedia.org/wiki/X86-64#Architectural_features


2
投票

由于x64上的规范,您可以依赖于总是适合IntPtr的用户空间指针。你不能依赖一个较小的空间。 CPU将来可以获得更多的地址线。如果在Windows 8和Windows 8.1之间发生这种情况,则不会添加向后兼容性标志。

实际上你在x86中得到了正指针和负指针,但是在IntPtr中存储指针仍然有效,因为0x7FFF0000的无人区和0x00000000的空陷阱范围。

我不认为你正在尝试做标记指针,但如果你是,那么做标记指针的唯一可接受的方法是最后两位。


1
投票

在Windows中,最大虚拟存储器地址是7FFF'FFFF'FFFF'FFFF,即,不可能在该地址之外分配存储器。从历史上看,AMD和Intel的第一批64位处理器(根据AMD64规范)仅支持48位地址。因此限制。

在这里查看更多详情:http://www.alex-ionescu.com/?p=50https://blogs.technet.microsoft.com/markrussinovich/2008/11/17/pushing-the-limits-of-windows-virtual-memory/

© www.soinside.com 2019 - 2024. All rights reserved.