news 2026/4/16 9:22:04

直接映射区的 MMU 处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
直接映射区的 MMU 处理

在讲解 MMU 处理逻辑前,先理清两个基础概念:

  • 直接映射区:内核将物理内存的前半部分(通常是0~896MB,即ZONE_DMA+ZONE_NORMAL)直接映射到虚拟地址空间的PAGE_OFFSET(x86 下是0xC0000000,ARM64 下是0xFFFF000000000000)开始的区域,物理地址和虚拟地址满足虚拟地址 = 物理地址 + PAGE_OFFSET
  • MMU 的核心作用:硬件层面完成虚拟地址 → 物理地址的转换,依赖页表(Page Table)实现,直接映射区的核心是让 MMU 能通过 “固定偏移” 的页表快速完成地址转换。

内核启动:构建直接映射区的页表

内核在start_kernel()之前的汇编 / 初始化阶段,会为直接映射区构建多级页表(x86_64 是 4 级:P4D→PUD→PMD→PTE;ARM64 是 4/5 级);

关键细节

  • 直接映射区的页表项(PTE)是静态构建的,物理地址和虚拟地址的偏移是固定值(PAGE_OFFSET),因此页表项的物理地址部分只需 “物理页框号(PFN)” 即可,无需动态计算。
  • 页表项的属性位(MMU 关注的核心):
    • PTE_P(Present):标记页有效,MMU 可访问;
    • PTE_RW(Read/Write):内核态可读写;
    • PTE_US(User/Supervisor):仅内核态可访问(用户态不可见);
    • PTE_PCD/PTE_PWT:缓存属性(直接映射区默认开启缓存,提升访问效率)。

MMU 必须遍历页表(硬件层面的硬性规则)

MMU 是硬件单元,它的核心工作机制就是通过遍历多级页表完成虚拟地址到物理地址的转换,这是 x86/ARM64 等架构的硬性规则,不会因为 “地址有固定偏移” 而改变:

  • 即使你知道直接映射区的 VA 和 PA 满足PA = VA - PAGE_OFFSET(软件层面的计算),但 MMU 硬件无法识别这个逻辑,它只能严格按照页表的索引规则去查找物理地址。
  • 举个通俗例子:你知道 “100 号房间 = 1 号楼层 + 99”,但酒店的门禁系统(MMU)不会认这个公式,必须刷房卡(查页表)才能开门。

为什么 “看起来像没遍历页表”?

你之所以会有这个疑问,本质是内核做了两层关键优化,让 “页表遍历” 的开销几乎可以忽略,甚至在软件层面能绕开遍历:

1. 硬件层面:TLB(快表)缓存页表转换结果

MMU 内置了 TLB(Translation Lookaside Buffer),这是页表转换结果的高速缓存:

  • 第一次访问直接映射区的某个虚拟地址时,MMU 会遍历页表完成转换,并将 “VA→PA” 的映射结果缓存到 TLB 中。
  • 后续访问同一段地址(或相邻地址)时,MMU 直接从 TLB 中读取转换结果,无需再次遍历页表(TLB 访问耗时仅 1~2 个时钟周期,远快于遍历多级页表)。
  • 直接映射区是内核最常访问的内存区域,TLB 命中率极高,因此实际的页表遍历操作极少发生。

2. 软件层面:直接地址计算(绕开 MMU 遍历)

内核代码中,经常直接用__pa(virt_addr)__va(phys_addr)宏计算地址,而不是依赖 MMU 的页表遍历:

// 示例:软件层面直接计算地址,无需触发MMU页表遍历 unsigned long virt_addr = (unsigned long)kmalloc(4096, GFP_KERNEL); phys_addr_t phys_addr = __pa(virt_addr); // 直接计算:phys_addr = virt_addr - PAGE_OFFSET // 反向计算 unsigned long virt_addr2 = __va(phys_addr); // virt_addr2 = phys_addr + PAGE_OFFSET
  • 这种方式仅适用于直接映射区(0~896MB 物理内存),因为只有这部分内存满足 “固定偏移” 规则。
  • 对于高端内存(>896MB),内核无法直接计算,必须通过 Fixmap/kmap 等机制构建页表,让 MMU 遍历页表完成转换。

大页映射:减少页表遍历的层级

内核会将直接映射区的连续物理内存映射为大页(如 x86_64 的 2MB/1GB 页):

  • 普通 4KB 页需要遍历 4 级页表(P4D→PUD→PMD→PTE);
  • 1GB 大页只需遍历 1 级页表(P4D)即可找到物理地址,大幅减少 MMU 遍历的层级和耗时。
  • 大页还能减少 TLB 缓存的条目数,提升 TLB 命中率(比如 1GB 大页只需 1 个 TLB 条目,而 4KB 页需要 262144 个)。

直观对比:直接映射区的地址转换流程

场景MMU 行为开销
首次访问某虚拟地址遍历多级页表 → 缓存到 TLB较高(单次)
后续访问同虚拟地址直接查 TLB → 无需遍历页表极低
软件层面计算地址完全绕开 MMU,直接通过偏移计算
大页映射的地址访问遍历更少层级的页表 → 缓存到 TLB较低

关键宏 / 函数(辅助 MMU 处理直接映射区)

宏 / 函数作用
__va(phys_addr)物理地址转直接映射区虚拟地址(VA = PA + PAGE_OFFSET
__pa(virt_addr)直接映射区虚拟地址转物理地址(PA = VA - PAGE_OFFSET
pgd_offset_k()获取内核虚拟地址对应的 PGD(页全局目录)项地址
flush_tlb_all()刷新 MMU 的 TLB(快表),确保页表修改生效

总结

  1. 硬件层面:MMU 访问直接映射区时必须遍历页表(这是 MMU 的核心工作机制),但 TLB 会缓存转换结果,让后续访问无需遍历。
  2. 软件层面:内核可通过__pa/__va宏直接计算地址,绕开 MMU 的页表遍历(仅适用于直接映射区)。
  3. 优化手段:大页映射减少页表遍历层级、TLB 提升缓存命中率,让直接映射区的 MMU 处理开销几乎可以忽略。
  4. 内核通过大页、地址宏(__va/__pa)等优化手段,降低 MMU 地址转换的开销,提升直接映射区的访问效率。
  5. 直接映射区的页表属性默认开启缓存、仅内核可访问,MMU 依赖页表项的权限位控制地址访问的合法性。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 9:21:37

计算机Java毕设实战-基于Springboot框架下中药材科普系统的开发与应用基于springboot的中药科普知识平台的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/3/28 7:22:31

改进的USBASP模块

简 介: 本文介绍了改进版USBASP下载模块的制作过程。主要改进包括:将12MHz晶体改为表贴式以缩小体积,增加独立负载电源接口,在USB D-线添加上拉电阻使Mega8可识别为低速USB模式,优化跳线设计实现单面PCB制作。通过一分…

作者头像 李华
网站建设 2026/4/16 9:21:56

AI4Science的前沿公司:Polymathic AI

1. 摘要 在当前的人工智能(AI)浪潮中,公众与市场的目光往往聚焦于以大语言模型(LLM)为代表的生成式 AI,其商业逻辑通常围绕“软件即服务”(SaaS)或API调用的变现模式展开。然而&…

作者头像 李华
网站建设 2026/3/31 18:35:01

1.2 一句话说清 Agent 和普通程序到底差在哪

1.2 一句话说清:Agent 和普通程序到底差在哪 本节学习目标 用一句话精确定义 Agent,并能向他人解释清楚。 掌握 Agent 的四大核心属性:自主感知、决策、行动、目标导向。 能区分「传统程序 / 传统自动化」与「Agent」,避免概念混淆。 一、一句话定义 一句话:Agent 是在给…

作者头像 李华
网站建设 2026/4/10 17:45:47

第1章 程序点滴程序点滴-1.1 程序≠软件(2)

1.1.2 认清自己的发展如果连以上认识都不清楚,很可能就以为去书店买一本MFC高手速成之类的书,编两个程序就能成为软件高手。就好像这些书是“黄金”,我学两下,学会了VC、MFC,就能做一个软件拿出去卖了。这种想法也不是…

作者头像 李华