ARM64内存页大小之争:4KB内核如何支撑64KB大页进程 📅 发布时间:2026/9/1 2:29:32 👁 浏览次数: 如果你下载过 Linux 发行版或者各种跨平台软件包大概率会同时看到amd64和arm64两个版本。很多人第一反应是“架构不同选一个能用就行”但真正到了 ARM64 服务器或开发板上做性能调优时问题就远不是“选哪个安装包”那么简单了。其中一个最容易引起争议、也最影响性能的参数就是内存页大小到底是选 4KB还是选 64KBARM64 架构与 x86-64 有一个明显的差异它原生支持 4KB、16KB、64KB 三种基础页大小。而 Linux 内核在编译时只能选择一种作为全局的基本页大小。这意味着如果你为了兼容性和内存利用率选了 4KB内核地址空间和进程地址空间都会以 4KB 为粒度去建立页表如果你为了减少 TLB miss 选了 64KB又可能在内核内存管理、设备驱动兼容性上遇到麻烦。本文要做的不是简单讨论“4KB 好还是 64KB 好”而是围绕一个更有意思的实验展开在 4KB 内核上让一个用户态进程使用 64KB 乃至 2MB 的大块映射并分析背后的页表机制。这会涉及 ARM64 的双页表设计、TTBR0/TTBR1 的地址空间隔离、THP 与 hugetlb 的实现方式。读完这篇文章你会明白“4KB 内核托起 64KB 进程”这句话到底在说什么以及在真实项目中应该如何选择页面大小、如何验证大页是否真正生效、遇到问题时该从哪里排查。1. 这篇文章真正要解决的问题很多开发者在接触 ARM64 服务器时第一个困惑来自一份内核编译参数表CONFIG_ARM64_4K_PAGES、CONFIG_ARM64_16K_PAGES、CONFIG_ARM64_64K_PAGES三者只能选一个。这时候团队里通常会出现两种声音。一种声音说必须选 64KB。理由是数据库、内存型应用、网络转发服务对 TLB 命中率极其敏感64KB 大页可以让同样的 TLB 覆盖更大的内存区域性能提升明显。另一种声音说必须用 4KB。理由是很多第三方驱动、内核模块、用户态二进制都是按 4KB 页对齐假设来编译的如果换成 64KB容易出现兼容性问题而且 64KB 页在内核内存碎片管理上更粗糙小对象频繁分配反而浪费内存。这两种说法都有道理但很多人忽略了一个事实Linux 内核的“全局基本页大小”并不等于“用户进程只能用这个大小来映射内存”。在 ARM64 上你可以让内核本身使用 4KB 页来管理内核地址空间同时让用户态进程通过透明大页THP或 hugetlb 获得 64KB、2MB 甚至更大的连续映射。这才是“4KB 内核托起 64KB 进程”的关键。这篇文章核心要解决的问题有四个第一ARM64 的双页表机制到底是什么。很多人以为“双页表”是指两份配置实际上它更接近 ARM64 硬件设计中的 TTBR0/TTBR1 分离以及虚拟化场景下 stage-1/stage-2 两级地址翻译。第二为什么内核和用户空间可以使用不同的映射粒度。这涉及页表层级、页大小与 TLB 覆盖范围的关系。第三如何在一个实实在在的实验环境里把 4KB 内核跑起来再让进程用上 64KB 大页并通过/proc接口验证效果。第四真实项目中选 4KB 还是 64KB 时该怎么思考和验证。没有哪套参数是银弹关键是理解代价和收益。什么样的读者最应该读这篇文章如果你正在做 ARM64 服务器内核移植、容器运行时调优、数据库性能优化或者只是好奇 ARM64 页表和大页机制这篇文章都适合你。2. ARM64 页表的核心概念在深入实验之前先把几个基础概念理清楚。这里不做长篇大论只讲后续实验必须用到的部分。2.1 页表、页大小和 TLB操作系统的地址翻译过程本质上是“虚拟地址到物理地址”的转换。转换依靠页表完成页表把虚拟地址空间切成固定大小的“页”每一页对应一条页表项。CPU 为了加速这个过程会在内部维护一个缓存叫 TLB。TLB 命中的时候地址翻译基本不耗时TLB miss 的时候CPU 必须遍历内存里的多级页表开销会明显增加。页大小直接影响 TLB 的覆盖范围。假设 TLB 有 512 个条目使用 4KB 页时最多覆盖 512 × 4KB 2MB 的热点内存使用 64KB 页时同样 512 个条目可以覆盖 512 × 64KB 32MB 的热点内存。对于内存访问局部性好、热点集中的程序64KB 页带来的 TLB miss 减少是肉眼可见的。2.2 ARM64 支持哪几种页大小ARMv8-A 架构规范里标准支持的基础页大小有三种基础页大小常见页表层级常见地址空间宽度典型使用场景4KB4 级48 位通用 Linux 内核默认、兼容性最好16KB4 级48 位个别嵌入式场景64KB4 级部分实现支持到 52 位高性能计算、数据中心、数据库场景Linux 内核在 ARM64 上编译时通过 Kconfig 在这三种里选一种作为基本页大小。这也意味着一个内核镜像只能有一个基础页大小不能“一半 4KB、一半 64KB”共存。注意这句话说的是“基础页大小”不是“映射粒度”。用户空间能不能用大页另说。2.3 双页表的第一个含义TTBR0 与 TTBR1ARM64 CPU 地址翻译时有两个页表基地址寄存器TTBR0 和 TTBR1。它们的用途很明确TTBR0 指向用户空间页表低地址区域通常在 EL0 下使用。TTBR1 指向内核空间页表高地址区域通常在 EL1 以上使用。进程切换时系统会切换 TTBR0 指向的页表而 TTBR1 指向的内核页表通常是全局共享的。这就是“双页表”的最直接体现用户态和内核态使用两套独立的页表结构互不干扰。这也解释了为什么在 ARM64 上内核和用户进程理论上可以采用不同的页表策略。内核的 vmalloc 区域、线性映射区域可以用 4KB 粒度来管理用户进程的匿名内存则可以通过 THP 或 hugetlb 生成更粗粒度的映射。2.4 双页表的第二个含义stage-1 与 stage-2如果你接触过 KVM 或虚拟化还会看到另一种双页表stage-1 和 stage-2。stage-1 负责虚拟地址VA到中间物理地址IPA的转换由 guest OS 管理。stage-2 负责 IPA 到真实物理地址PA的转换由 hypervisor 管理。在 KVM 场景里一个 guest 使用 64KB 页host 使用 4KB 页完全是可以共存的。host 的 stage-2 页表可以按 4KB 粒度建立guest 的 stage-1 页表则按 64KB 粒度建立。这种组合在云厂商的 ARM64 实例里很常见也是“双页表”在虚拟化语境下的重要含义。2.5 contiguous bit大页映射的硬件基础ARM64 页表项里有一个特殊的位叫 Contiguous bit。它允许软件把 16 个连续且属性相同的页面标记为一个“块”TLB 可以只用一个条目来缓存这一整块区域。对于 4KB 基础页16 个连续页正好是 64KB对于 64KB 基础页16 个连续页则是 1MB。这正是“4KB 内核托起 64KB 进程”的硬件底座之一内核的页表仍然用 4KB 条目但通过 contiguous bit 让 TLB 以 64KB 的粒度工作最终效果接近真正的 64KB 页。3. 为什么会有 4KB 与 64KB 之争理解了页表机制就能明白这场争论的实质其实是在内存利用率和 TLB 效率之间做权衡。3.1 4KB 页的优势与代价4KB 页的最大优势是兼容性好。Linux 内核主线的默认配置、绝大多数驱动源码、用户态动态库都默认按 4KB 页对齐来编译。4KB 作为基本页大小物理页分配更灵活可以降低内部碎片。比如一个进程只需要 10KB 内存用 4KB 页需要 3 个物理页浪费 2KB 左右用 64KB 页则需要 1 个 64KB 物理页浪费 54KB。代价也明显页表条目更多TLB 覆盖范围小随机访问大内存时 TLB miss 更频繁。3.2 64KB 页的优势与代价64KB 页的优势正好反过来。页表条目更少TLB 覆盖范围更大遍历页表的层级开销也会降低。对于数据库缓冲池、内存文件系统、大流量网络转发这类“内存很大、热点集中”的场景64KB 页带来的收益可能非常可观。代价是物理内存管理粒度变粗小对象分配容易浪费内存第三方驱动如果没适配 64KB 页可能会出问题某些用户态程序如果假设页大小是 4KB也会踩坑。比如 Go runtime 在部分版本里对syscall.Mmap的对齐处理就很敏感换到 64KB 基本页后偶尔会出现内存对齐相关的问题。3.3 两边都不完美所以才有实验空间如果整个系统只能固定一个基本页大小那么注定无法同时满足所有场景。这也是本文实验的价值所在内核保持 4KB兼容性和内存利用率不下降用户态通过大页机制获得接近 64KB 的 TLB 覆盖效果性能敏感型应用因此受益。从工程角度看这不是“二选一”而是“分层选择”内核层用 4KB 保证稳定用户层按场景选择 THP 或 hugetlb。4. 实验环境准备与前置条件下面进入实验环节。因为涉及内核配置和启动推荐使用 QEMU 模拟 ARM64 环境这样可以在不占用真实 ARM64 机器的情况下完成验证。4.1 需要的软件与工具建议准备以下工具工具用途QEMU for ARM64模拟 ARM64 虚拟机aarch64-linux-gnu-gcc交叉编译内核和测试程序Linux 内核源码编译 ARM64 内核rootfs如 Debian/Ubuntu ARM64 镜像提供用户态运行环境版本号不需要刻意追新建议使用你熟悉的稳定版本即可。本文重点演示通用思路具体版本以实际环境为准。4.2 安装 QEMU 与交叉编译器在 Ubuntu/Debian 系统上可以直接安装sudo apt update sudo apt install qemu-system-arm qemu-efi-aarch64 \ gcc-aarch64-linux-gnu cpio xz-utils其他发行版类似关键是装好qemu-system-aarch64和aarch64-linux-gnu-gcc。4.3 获取 Linux 内核源码并配置下载内核源码后先进行基础配置make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- defconfig然后打开 menuconfig确认页面大小相关选项make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- menuconfig在Kernel Features-Page size菜单下可以看到三选一的配置[ ] 4KB pages [ ] 16KB pages [ ] 64KB pages这里我们选择 4KB pages。不用怀疑这没错因为实验目标就是“4KB 内核托起 64KB 进程”。同时需要打开 THP 和 hugetlb 支持。在内核配置文件中类似下面这些配置需要确保开启CONFIG_ARM64_4K_PAGESy CONFIG_TRANSPARENT_HUGEPAGEy CONFIG_HUGETLBFSy CONFIG_HUGETLB_PAGEy你可以直接编辑.config文件再执行make olddefconfig让它自动补齐依赖sed -i s/# CONFIG_TRANSPARENT_HUGEPAGE is not set/CONFIG_TRANSPARENT_HUGEPAGEy/ .config sed -i s/# CONFIG_HUGETLBFS is not set/CONFIG_HUGETLBFSy/ .config sed -i s/# CONFIG_HUGETLB_PAGE is not set/CONFIG_HUGETLB_PAGEy/ .config make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- olddefconfig4.4 编译内核make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- -j$(nproc) Image编译产物是arch/arm64/boot/Image后面 QEMU 启动时会用到。4.5 准备 rootfs最省事的方式是直接使用现成的 ARM64 云镜像或 Debian rootfs。这里不展开完整的 rootfs 制作流程只要你能得到一个可以用 virtio 块设备挂载的 rootfs 镜像即可。比如# 假设下载好的 rootfs 镜像叫 arm64-rootfs.img # 如果有需要可以先用 virt-customize 做基础配置5. 双页表实验的核心流程实验分四步走确认内核基本页大小、启动系统、编写测试程序、检查当前 THP 配置并让进程映射大页。下面逐步拆解。5.1 确认内核基本页大小启动系统后用下面的命令查看当前内核的基本页大小getconf PAGE_SIZE如果输出4096说明当前内核确实是 4KB 基本页。这一步是整个实验的前提如果这里输出的是65536那就不是“4KB 内核托起 64KB 进程”了而是纯粹的 64KB 内核。5.2 查看透明大页配置透明大页THP是让用户进程自动获得大页映射的最常用机制。在 ARM64 4KB 内核上它通常会把相邻的 512 个 4KB 页合并成一个 2MB 的映射。如果内核同时启用了 contiguous bitTLB 可以按 64KB 粒度缓存其中的一部分这正是我们需要的效果。查看当前 THP 状态cat /sys/kernel/mm/transparent_hugepage/enabled可能的输出[always] madvise never方括号所在的位置代表当前策略。always表示系统尝试自动合并大页madvise表示只有进程主动调用madvise(MADV_HUGEPAGE)时才启用never表示关闭。对实验来说临时改成madvise更可控echo madvise /sys/kernel/mm/transparent_hugepage/enabled这样只有我们指定的进程会使用大页其他进程保持默认 4KB 映射便于对比。5.3 检查 hugetlb 支持如果不用 THP也可以使用 hugetlb。hugetlb 需要提前预留大页。在 4KB 基本页的 ARM64 内核上常见的 hugetlb 大小有 64KB、2MB 等具体取决于内核是否编译了对应的大页大小支持。ls /sys/kernel/mm/hugepages/如果看到类似hugepages-64kB目录说明内核支持 64KB hugetlb 页。预留页面示例echo 64 /sys/kernel/mm/hugepages/hugepages-64kB/nr_hugepages不过这里要提醒一下64KB hugetlb 页并非所有内核配置都默认开启。如果当前环境不支持优先用 2MB THP 做验证原理是一样的。5.4 用 QEMU 启动 4KB 内核假设你已经准备好了Image和 rootfs可以用下面的 QEMU 命令启动qemu-system-aarch64 \ -machine virt \ -cpu cortex-a72 \ -smp 4 \ -m 4096 \ -kernel Image \ -drive filearm64-rootfs.img,formatraw,ifvirtio \ -append consolettyAMA0 root/dev/vda rw transparent_hugepagemadvise \ -nographic这条命令比较长但每一段都有明确作用-machine virt使用 ARM64 virt 虚拟平台这是 QEMU 对 ARM64 支持最成熟的机型。-cpu cortex-a72模拟 ARMv8-A 64 位 CPU。-smp 44 个 vCPU。-m 40964GB 内存。-kernel Image加载编译好的内核镜像。-drive把 rootfs 挂成 virtio 块设备。-append传入内核启动参数。transparent_hugepagemadvise是内核参数写法效果和在 sysfs 里设置一样但启动阶段就生效。如果 rootfs 默认没有配置串口登录可以在启动参数里加init/bin/bash直接进入 shell便于最小化实验。6. 完整示例代码实现进入系统后写一个最小的 C 程序尝试分配一段 2MB 内存并通过madvise告诉内核我们希望使用大页。6.1 测试程序mmap 与 madvise文件路径/root/thp_test.c#define _GNU_SOURCE #include stdio.h #include stdlib.h #include string.h #include sys/mman.h #include unistd.h #include fcntl.h int main(void) { size_t len 2 * 1024 * 1024; /* 2MB */ unsigned char *addr; long page_size; page_size sysconf(_SC_PAGESIZE); printf(PAGE_SIZE from system: %ld\n, page_size); /* 分配 2MB 匿名内存mmap 返回值按页对齐 */ addr mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (addr MAP_FAILED) { perror(mmap); return 1; } /* 明确告诉内核这段内存希望使用大页映射 */ if (madvise(addr, len, MADV_HUGEPAGE) ! 0) { perror(madvise); } /* 写一点内容触发缺页和物理页分配 */ memset(addr, 0xAB, len); printf(mmap addr: %p, len: %zu\n, addr, len); printf(touch done. now check /proc/self/smaps\n); /* 保持进程不退出便于另一个终端查看 smaps */ sleep(20); munmap(addr, len); return 0; }编译aarch64-linux-gnu-gcc -static -O2 -o thp_test thp_test.c-static是为了避免动态库依赖带来的干扰静态编译在实验环境里更稳。6.2 查看 smaps 验证大页在程序运行时在另一个终端查看grep -E KernelPageSize|MMUPageSize|AnonHugePages /proc/$(pgrep thp_test)/smaps这里解释一下三个字段KernelPageSize内核使用的基本页大小在 4KB 内核上应该显示 4KB。MMUPageSizeMMU 实际映射的页面大小。如果大页生效可能显示 2MB 甚至 64KB 的组合粒度。AnonHugePages这段地址空间里匿名大页占用的总大小。如果输出类似KernelPageSize: 4 kB MMUPageSize: 4 kB AnonHugePages: 2048 kB说明进程确实有一块 2MB 的匿名内存被映射成了大页。注意在 4KB 基本页的 ARM64 内核上THP 通常表现为 2MB 大页而 64KB 的块效果来自相邻 4KB 页的 TLB 合并这就是“4KB 内核托起 64KB 进程”在硬件层面的体现。6.3 使用 hugetlb 的替代验证如果你的内核支持 64KB hugetlb 页可以用下面的 C 片段验证#define _GNU_SOURCE #include stdio.h #include sys/mman.h int main(void) { void *addr; FILE *fp fopen(/sys/kernel/mm/hugepages/hugepages-64kB/nr_hugepages, w); if (fp) { fputs(64, fp); fclose(fp); } addr mmap(NULL, 64 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); if (addr MAP_FAILED) { perror(mmap hugetlb); return 1; } printf(hugetlb 64KB mapping at %p\n, addr); getchar(); return 0; }MAP_HUGETLB标志会让内核从预留的 hugetlb 池里分配大页。程序运行后再次看 smaps会看到MMUPageSize不再是 4KB。6.4 检查物理页映射层次的工具如果想深入确认页表结构可以读取/proc/self/pagemap但它每一位的含义比较繁琐而且需要 root 权限。更直观的做法是使用pagemap相关工具或直接对比smaps中的大页字段。对大多数读者来说smaps已经足够。7. 运行结果与效果验证实验到这里我们已经具备判断“是否成功”的标准。7.1 判断步骤第一步确认内核基本页大小是 4KBgetconf PAGE_SIZE # 期望输出 4096第二步确认 THP 策略可控cat /sys/kernel/mm/transparent_hugepage/enabled # 输出包含 madvise第三步运行测试程序并观察大页字段./thp_test # 另一个终端执行 cat /proc/$(pgrep thp_test)/smaps | grep -E AnonHugePages|KernelPageSize|MMUPageSize如果AnonHugePages大于 0说明 THP 已经触发。7.2 预期输出示例在 4KB 内核上运行测试程序预期是PAGE_SIZE from system: 4096 mmap addr: 0xffff8f44a000, len: 2097152 touch done. now check /proc/self/smapssmaps 中可能出现KernelPageSize: 4 kB MMUPageSize: 4 kB AnonHugePages: 2048 kB这里最值得关注的是AnonHugePages。一个 2MB 的匿名映射被合并成大页说明内核成功在 4KB 页面体系上为用户进程构造了大块映射。如果使用的是 hugetlb 64KB 映射smaps 中对应区域的MMUPageSize会显示 64KB。7.3 如何判断是否失败如果AnonHugePages始终为 0优先检查三点是否真的把 THP 策略改成了always或madvise。内存是否连续。THP 在内存碎片严重时可能合并失败此时可以尝试增大内存或先执行echo 3 /proc/sys/vm/drop_caches清理缓存。架构是否支持。ARM64 上 4KB 页的 THP 通常只支持 2MB 大页如果程序只映射了 1MB内核很难合并出完整的大页。8. 常见问题与排查思路问题现象可能原因排查方式解决方案getconf PAGE_SIZE输出 65536内核编译时选择了 64KB 基本页查看内核.config中的CONFIG_ARM64_4K_PAGES重新编译 4KB 内核确认依赖配置THP 不生效AnonHugePages为 0内存碎片严重或 mmap 长度不够检查/sys/kernel/mm/transparent_hugepage/enabled尝试清理缓存增大内存改用madvise映射至少 2MB程序无法启动rootfs 架构不匹配确认 rootfs 是 arm64 版本换用官方 ARM64 rootfsQEMU 启动后黑屏或卡住内核参数或串口配置错误检查-append中的consolettyAMA0尝试consolettyS0或其他串口名hugetlb 申请失败没有预留大页或权限不足查看/sys/kernel/mm/hugepages/目录先写nr_hugepages再确认是否有足够连续内存mmap返回ENOMEM内核没有开启对应大页支持检查内核配置中HUGETLBFS与指定大小页重新编译内核开启对应配置9. 最佳实践与工程建议实验跑通之后更要关注的是生产环境怎么选、怎么验证。9.1 生产环境优先确认基本页大小在部署 ARM64 服务时第一件事是确认运行环境的PAGE_SIZE。不要凭印象猜测。腾讯云、阿里云、AWS 的 ARM64 实例可能默认使用不同的页面大小。通过下面命令确认getconf PAGE_SIZE cat /proc/meminfo | grep PageSize如果应用依赖 4KB 页假设就不要部署在 64KB 基本页的镜像上如果应用需要大 TLB 覆盖再考虑是否切换到 64KB 基本页或使用 THP。9.2 THP 不是所有场景都合适THP 的always模式会让系统自动尝试合并大页这对内存占用大、访问集中的服务有利但可能增加内存分配延迟。延迟敏感型实时任务通常建议使用madvise让程序员在明确需要大页的路径上主动声明。对数据库这类对性能敏感的应用建议做一次 AB 对比# 场景 A关闭 THP echo never /sys/kernel/mm/transparent_hugepage/enabled # 场景 B开启 THP echo always /sys/kernel/mm/transparent_hugepage/enabled然后分别跑同一个压测任务观察吞吐、P99 延迟和 TLB miss 数据。不要凭感觉拍板。9.3 hugetlb 更适合确定性的内存预留如果服务进程需要固定大小的内存池比如 DPDK、KVM guest 内存、大型数据缓存推荐使用 hugetlb 而不是 THP。hugetlb 在启动阶段或运行前预留物理页分配路径更短性能更稳定也避免了运行时内存碎片导致的大页合并失败。预留 2MB 大页的示例echo 1024 /proc/sys/vm/nr_hugepages如果内核支持 64KB hugetlb 页echo 256 /sys/kernel/mm/hugepages/hugepages-64kB/nr_hugepages9.4 注意用户态程序的对齐假设很多用户态程序默认PAGE_SIZE是 4KB。当进程通过大页获得 64KB 映射时如果程序内部使用mmap 页对齐来计算缓冲区边界可能出现指针越界或地址计算错误。常见做法是使用posix_memalign配合页大小对齐而不是硬编码 4096。建议在代码里动态获取long page_size sysconf(_SC_PAGESIZE);或者显式声明依赖于 hugetlb 的场景#define HUGEPAGE_SIZE (2 * 1024 * 1024)9.5 KVM 场景host 与 guest 页面大小可以不同在 KVM 虚拟化环境里host 用 4KB 页、guest 用 64KB 页是常见组合。此时 host 的 stage-2 页表负责把 guest 的 64KB 物理页映射到 host 物理内存可能需要把 64KB 拆成 16 个 4KB 页来建立 stage-2 页表。这会让 TLB 效率下降所以不少 hypervisor 会在支持时把 stage-2 也做成大页映射。如果你的 ARM64 云环境性能不符合预期可以把 host 内核的CONFIG_ARM64_64K_PAGES与 guest 内核配置结合起来测试。9.6 线上变更要有回滚方案修改内核参数、预留 hugetlb、切换 THP 策略都属于内核级变更。生产环境操作前务必先做备机验证并保留一键恢复脚本。特别是修改/sys/kernel/mm/transparent_hugepage/enabled这类运行时参数重启后会恢复默认值要确认你的初始化脚本是否符合预期。10. 总结与后续学习方向这个实验看起来只是“改一个配置、跑一段 mmap 代码”但它背后涉及的东西远不止这些。你通过这个实验验证了四件事ARM64 内核可以保持 4KB 基本页保证兼容性用户进程可以通过 THP 或 hugetlb 使用大块映射获得 TLB 效率ARM64 的 TTBR0/TTBR1 双页表机制让内核和用户空间可以有不同的页表行为在 KVM 等虚拟化场景中stage-1 和 stage-2 双页表还能让不同虚拟机使用不同页面大小。如果你还想深入建议按这个顺序继续学习第一阅读 ARMv8-A 架构手册中关于 Translation table format 和 Contiguous bit 的章节搞清楚页表项里每一位的作用。第二在内核源码里搜索trans_hugepage和hugetlb相关实现重点看 ARM64 的arch/arm64/mm/hugetlbpage.c和arch/arm64/mm/pageattr.c理解内核如何组合 4KB 页形成大块映射。第三尝试在 KVM 场景下做一次 host 4KB、guest 64KB 的交叉实验观察guest内部getconf PAGE_SIZE和 host 侧的 stage-2 页表开销。页面大小的选择本质上是工程权衡不是一个“越大越好”或者“越小越好”的问题。真正重要的是你能随时用工具确认系统当前处于什么状态能解释现象背后的页表机制并且在业务出现性能瓶颈时知道往哪个方向验证。动手把 4KB 内核和 64KB 进程这个组合跑通一次对理解 ARM64 内存管理会有很大帮助。