GetSystemInfo函数可获取Windows虚拟内存的页面大小和分配粒度:dwPageSize通常为4096字节(默认页大小),dwAllocationGranularity恒为65536字节(64KB,VirtualAlloc地址对齐单位)。

Windows 下用 GetSystemInfo 获取页面大小和最小分配粒度
Windows 系统的虚拟内存分页配置中,最常被需要的是页面大小(page size)和内存分配粒度(allocation granularity)。这两个值不等于 CPU 的硬件页大小(如 4KB),而是 Windows 内存管理器对外暴露的“软件可见粒度”。GetSystemInfo 是唯一轻量、无需权限、全版本兼容的获取方式。
常见错误是误以为 dwPageSize 就是 TLB 或 MMU 使用的底层页大小——其实它只是 VirtualAlloc 默认对齐单位;真正影响 VirtualAlloc 地址对齐的是 dwAllocationGranularity(通常为 64KB)。
-
dwPageSize一般为 4096(即 4KB),但某些 ARM64 或启用了 2MB 大页的系统可能返回其他值,必须运行时读取 -
dwAllocationGranularity在 x64 Windows 上恒为 65536(64KB),这是VirtualAlloc的lpAddress参数必须对齐的最小单位 - 示例代码片段:
SYSTEM_INFO si; GetSystemInfo(&si); printf("Page size: %lu bytes\n", si.dwPageSize); printf("Allocation granularity: %lu bytes\n", si.dwAllocationGranularity);
Linux 下读取 /proc/meminfo 和 getconf 的区别
Linux 没有统一 API 返回“虚拟内存分页配置”,需组合多个来源:硬件页大小靠 getconf PAGESIZE(对应 getpagesize()),而大页支持情况要查 /proc/meminfo 中的 HugePages_Total、Hugepagesize 等字段。
容易踩的坑是把 getpagesize() 当作唯一标准——它只返回默认基页大小(通常 4KB),完全不反映透明大页(THP)或显式 hugetlbpage 配置。实际 mmap 分配是否启用大页,取决于 mmap 调用时的 MAP_HUGETLB 标志和内核配置。
立即学习“C++免费学习笔记(深入)”;
-
getconf PAGESIZE命令或getpagesize()函数返回的是sysconf(_SC_PAGESIZE),稳定可靠,但仅限基页 -
/proc/meminfo中的Hugepagesize表示当前启用的默认大页尺寸(如 2048 kB),但该值可能为 0(未启用 hugetlbpage) - 若需判断 THP 是否启用,应检查
/sys/kernel/mm/transparent_hugepage/enabled,内容可能是[always] madvise never,方括号内为当前模式
跨平台 C++ 封装建议:避免硬编码 4096
很多老代码直接写死 4096 当页面大小,这在 Windows ARM64(可能为 64KB)、某些嵌入式 Linux 或开启大页的场景下会出错。真实项目里应封装一次初始化逻辑,缓存系统实际值。
关键点不是“怎么读”,而是“读完怎么用”:比如计算地址对齐时,VirtualAlloc 要求地址按 dwAllocationGranularity 对齐,而 mmap 的 addr 参数推荐按 getpagesize() 对齐(否则可能失败或降级)。
- Windows:优先使用
dwAllocationGranularity对齐申请地址,dwPageSize用于计算保护粒度(如VirtualProtect) - Linux:用
getpagesize()对齐mmap地址;若需大页,额外检查/proc/meminfo并显式传MAP_HUGETLB - 不要在编译期用
#define PAGE_SIZE 4096,改用运行时变量 +const初始化,例如:static const size_t kPageSize = getpagesize();
为什么 GetNativeSystemInfo 和 IsWow64Process 在这里不相关
有人看到文档里提到 GetNativeSystemInfo 就想用它替代 GetSystemInfo,其实没必要。前者只在 WoW64(32 位进程跑在 64 位系统)下返回宿主系统的真实信息,而虚拟内存分页配置对 32/64 位进程是同一套策略——GetSystemInfo 返回的就是当前进程视角下有效的值。
同理,IsWow64Process 只用于判断进程是否处于模拟环境,和页面大小、分配粒度无任何关系。强行调用只会增加冗余判断,还可能因权限或 API 不可用引入失败分支。
-
GetSystemInfo已足够:它返回的是当前进程能实际使用的内存管理参数 - 除非你在写反作弊或内核驱动工具,否则不需要区分“原生”和“模拟”下的页表结构
- 真正影响行为的是
VirtualAlloc的flAllocationType(如MEM_COMMIT)和flProtect,不是系统信息函数选哪个
dwAllocationGranularity 虽然固定为 64KB,但如果你用 VirtualAlloc 分配小于 64KB 的区域,系统仍会按 64KB 占用 VAD(Virtual Address Descriptor)条目——这意味着大量小内存块会导致地址空间碎片化,比页大小本身更值得监控。



















