64 位 Windows 可以分配超过 7FFF'FFFF'FFFF 的虚拟内存吗?
May 64-bit Windows allocate virtual memory over 7FFF'FFFF'FFFF?
上下文
我正在努力升级 .NET 库以支持 64 位。该库直接在 Windows 上其他进程的内存中执行各种操作。我必须在两种类型 IntPtr
(最大正值 7FFF'FFFF'FFFF'FFFF)或 UIntPtr
(最大正值 FFFF'FFFF'FFFF'FFFF)之间进行选择来处理我的内存指针。网上关于这两者的资料很多。 IntPtr
似乎是 事实上 同意的选择,因为它符合 CLS 并且大多数 .NET API 都依赖于此(参考 Marshal
来自 InteropServices
).
问题
我决定打开一个 64 位进程并检查分配的内存区域,以及进程中加载的模块,看看使用 UIntPtr
支持无符号指针是否有价值(地址 > 7FFF'FFFF'FFFF'FFFF)。如下图所示,内存地址似乎没有加载符号,也没有分配超过 7FFF'FFFF'FFFF 的内存。这样做有具体原因吗?在某些情况下,Windows 可以在该值上分配内存区域吗?
在Windows中,最大虚拟内存地址为7FFF'FFFF'FFFF'FFFF,即不能分配超出该地址的内存。从历史上看,AMD 和 Intel 的第一批 64 位处理器(根据 AMD64 规范)仅支持 48 位地址。因此限制。
在此处查看更多详细信息:
http://www.alex-ionescu.com/?p=50
和
https://blogs.technet.microsoft.com/markrussinovich/2008/11/17/pushing-the-limits-of-windows-virtual-memory/
由于 x64 规范,您可以依赖用户space 始终适合 IntPtr
的指针。您不能依赖较小的 space。 CPU 将来可以获得更多地址行。当这发生在 Windows 8 和 Windows 8.1 之间时,没有添加向后兼容性标志。
事实上,您在 x86 中同时获得了正指针和负指针,但是在 IntPtr
中存储指针仍然有效,因为 0x7FFF0000
处的无人区和 [= 处的空陷阱范围13=].
我不认为你在尝试做标记指针,但如果你是,唯一可接受的做标记指针的方法是底部的两位。
在Windows中每个进程只有一个地址space8TB,因此用户代码的上限是0x7FF'FFFF'FFFF
The range of virtual addresses that is available to a process is called the virtual address space for the process. Each user-mode process has its own private virtual address space. For a 32-bit process, the virtual address space is usually the 2-gigabyte range 0x00000000 through 0x7FFFFFFF. For a 64-bit process, the virtual address space is the 8-terabyte range 0x000'00000000 through 0x7FF'FFFFFFFF. A range of virtual addresses is sometimes called a range of virtual memory.
This diagram illustrates some of the key features of virtual address spaces.
https://docs.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/virtual-address-spaces
高248TB属于内核态,加起来就是256TB的地址space,用48位寻址。这意味着最高可能的正地址是 247-1 = 0x7FFF'FFFF'FFFF
In 64-bit Windows, the theoretical amount of virtual address space is 2^64 bytes (16 exabytes), but only a small portion of the 16-exabyte range is actually used. The 8-terabyte range from 0x000'00000000 through 0x7FF'FFFFFFFF is used for user space, and portions of the 248-terabyte range from 0xFFFF0800'00000000 through 0xFFFFFFFF'FFFFFFFF are used for system space.
更新:
如下所述,在 Windows 8.1 和 Windows Server 2012 R2 或更高版本中,user/kernel 地址 space 拆分为 128/128TB,总计相同256TB space
重要部分是 48 位宽可能是因为大多数当前 x86-64 实现使用 48 位虚拟地址
The original implementation of the AMD64 architecture implemented 40-bit physical addresses and so could address up to 1 TB (240 bytes) of RAM. Current implementations of the AMD64 architecture (starting from AMD 10h microarchitecture) extend this to 48-bit physical addresses and therefore can address up to 256 TB of RAM. The architecture permits extending this to 52 bits in the future (limited by the page table entry format); this would allow addressing of up to 4 PB of RAM.
上下文
我正在努力升级 .NET 库以支持 64 位。该库直接在 Windows 上其他进程的内存中执行各种操作。我必须在两种类型 IntPtr
(最大正值 7FFF'FFFF'FFFF'FFFF)或 UIntPtr
(最大正值 FFFF'FFFF'FFFF'FFFF)之间进行选择来处理我的内存指针。网上关于这两者的资料很多。 IntPtr
似乎是 事实上 同意的选择,因为它符合 CLS 并且大多数 .NET API 都依赖于此(参考 Marshal
来自 InteropServices
).
问题
我决定打开一个 64 位进程并检查分配的内存区域,以及进程中加载的模块,看看使用 UIntPtr
支持无符号指针是否有价值(地址 > 7FFF'FFFF'FFFF'FFFF)。如下图所示,内存地址似乎没有加载符号,也没有分配超过 7FFF'FFFF'FFFF 的内存。这样做有具体原因吗?在某些情况下,Windows 可以在该值上分配内存区域吗?
在Windows中,最大虚拟内存地址为7FFF'FFFF'FFFF'FFFF,即不能分配超出该地址的内存。从历史上看,AMD 和 Intel 的第一批 64 位处理器(根据 AMD64 规范)仅支持 48 位地址。因此限制。
在此处查看更多详细信息: http://www.alex-ionescu.com/?p=50 和 https://blogs.technet.microsoft.com/markrussinovich/2008/11/17/pushing-the-limits-of-windows-virtual-memory/
由于 x64 规范,您可以依赖用户space 始终适合 IntPtr
的指针。您不能依赖较小的 space。 CPU 将来可以获得更多地址行。当这发生在 Windows 8 和 Windows 8.1 之间时,没有添加向后兼容性标志。
事实上,您在 x86 中同时获得了正指针和负指针,但是在 IntPtr
中存储指针仍然有效,因为 0x7FFF0000
处的无人区和 [= 处的空陷阱范围13=].
我不认为你在尝试做标记指针,但如果你是,唯一可接受的做标记指针的方法是底部的两位。
在Windows中每个进程只有一个地址space8TB,因此用户代码的上限是0x7FF'FFFF'FFFF
The range of virtual addresses that is available to a process is called the virtual address space for the process. Each user-mode process has its own private virtual address space. For a 32-bit process, the virtual address space is usually the 2-gigabyte range 0x00000000 through 0x7FFFFFFF. For a 64-bit process, the virtual address space is the 8-terabyte range 0x000'00000000 through 0x7FF'FFFFFFFF. A range of virtual addresses is sometimes called a range of virtual memory.
This diagram illustrates some of the key features of virtual address spaces.
https://docs.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/virtual-address-spaces
高248TB属于内核态,加起来就是256TB的地址space,用48位寻址。这意味着最高可能的正地址是 247-1 = 0x7FFF'FFFF'FFFF
In 64-bit Windows, the theoretical amount of virtual address space is 2^64 bytes (16 exabytes), but only a small portion of the 16-exabyte range is actually used. The 8-terabyte range from 0x000'00000000 through 0x7FF'FFFFFFFF is used for user space, and portions of the 248-terabyte range from 0xFFFF0800'00000000 through 0xFFFFFFFF'FFFFFFFF are used for system space.
更新:
如下所述,在 Windows 8.1 和 Windows Server 2012 R2 或更高版本中,user/kernel 地址 space 拆分为 128/128TB,总计相同256TB space
重要部分是 48 位宽可能是因为大多数当前 x86-64 实现使用 48 位虚拟地址
The original implementation of the AMD64 architecture implemented 40-bit physical addresses and so could address up to 1 TB (240 bytes) of RAM. Current implementations of the AMD64 architecture (starting from AMD 10h microarchitecture) extend this to 48-bit physical addresses and therefore can address up to 256 TB of RAM. The architecture permits extending this to 52 bits in the future (limited by the page table entry format); this would allow addressing of up to 4 PB of RAM.