You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux 2.6.26内核中swapper_pg_dir两次加载到cr3是否必要?

为什么Linux 2.6.26内核中swapper_pg_dir会被两次加载到cr3?

这是个相当精准的问题——内核启动阶段的分页机制细节很容易让人摸不着头脑,我来帮你拆解这两次加载的核心区别和必要性:

  • 第一次加载:开启分页的初始启动
    在arch/x86/kernel/head_32.S里的cr3加载,是内核从实模式切换到保护模式后,第一次启用分页的关键步骤。此时的swapper_pg_dir是一个极简的临时页表,只完成了最基础的映射:把内核的核心代码段(物理地址0到__PAGE_OFFSET的区域)映射到对应的虚拟地址空间。它的唯一目的是让内核快速进入分页模式,能在虚拟地址下运行,但这个页表并不完整——没有映射所有内核需要的内存区域,也没处理诸如权限、缓存策略、PAE(如果启用)这类高级内存管理设置。

  • 第二次加载:刷新TLB并应用完整页表
    到了arch/x86/mm/init_32.c第528行调用load_cr3(swapper_pg_dir)的时候,内核已经完成了大量内存初始化工作:swapper_pg_dir已经被扩展和修改,比如添加了更多内核区域的映射、调整了页表项的属性(比如某些区域的读写权限、是否允许缓存),甚至可能处理了PAE模式下的页表层级。

    这里的关键是**TLB(地址转换旁路缓冲)**的存在:CPU会缓存已经解析过的页表条目,直接修改页表内容后,CPU的TLB里可能还保留着旧的无效条目。而x86架构下,重新加载cr3寄存器是强制刷新TLB的标准方式——这会让CPU丢弃所有缓存的页表条目,重新从更新后的swapper_pg_dir中读取新的页表内容。

    哪怕你觉得此时swapper_pg_dir的物理地址没变化,这次加载依然有意义:它能确保分页状态的一致性,避免之前的初始化操作留下TLB脏数据,是内存管理流程中保证可靠性的必要步骤。

简单来说,两次加载的目标完全不同:第一次是“开启分页功能”,第二次是“让更新后的完整页表真正生效”,后者绝对是必不可少的。

内容的提问来源于stack exchange,提问作者Leo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:39:23