当前位置: 首页 > news >正文

【内存管理】设置内存页表项 set_pte_at

set_pte_at(&init_mm, addr, pte, mk_pte(page, prot)); 是 Linux 内核中用于 设置页表项(PTE) 的核心函数之一。其作用是将虚拟地址 addr 对应的页表项更新为 mk_pte(page, prot) 生成的值,并确保操作的安全性和正确性。以下是其原理和过程的详细分析:


1. 参数解析

  • &init_mm
    指向内核的内存描述符(mm_struct),表示当前操作的是内核页表(而非某个进程的页表)。
  • addr
    虚拟地址,用于定位需要修改的页表项(PTE)的位置。
  • pte
    新的 PTE 值,由 mk_pte(page, prot) 生成。
  • mk_pte(page, prot)
    构造一个 PTE,将物理页 page 和权限标志 prot 组合成页表项。

2. mk_pte(page, prot) 的作用

#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
  • page_to_pfn(page)
    pagestruct page 类型的物理页描述符)转换为物理页帧号(PFN)。
    • 实现:page - vmem_mapvmem_map 是物理页的基地址)。
  • pfn_pte(pfn, pgprot)
    将 PFN 和权限标志 pgprot 组合成一个 PTE 值。
    • 实现:
      static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) {return __pte((pfn << PAGE_SHIFT) | pgprot_val(pgprot));
      }
      
      • pfn << PAGE_SHIFT:将 PFN 转换为物理地址(假设页大小为 4KB)。
      • pgprot_val(pgprot):提取权限标志(如可读、可写、可执行等)。
      • __pte(...):将结果封装为 pte_t 类型。

示例
page 对应的 PFN 为 0x1000protPAGE_KERNEL(可读、可写、可执行),则生成的 PTE 为:

pte = 0x1000 << 12 | 0x7; // 0x1000000 + 0x7 = 0x1000007

3. set_pte_at 的执行流程

(1) 缓存同步(__sync_icache_dcache
if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))__sync_icache_dcache(pte);
  • 目的
    在某些架构(如 ARM64)中,如果 PTE 对应的页是可执行代码(pte_user_exec 为真),需要同步指令缓存(ICache)和数据缓存(DCache),以确保 CPU 读取最新的代码或数据。
  • 实现
    __sync_icache_dcache 会触发硬件指令(如 ISBDCIVAC),使缓存一致性生效。
(2) 竞态检查(__check_racy_pte_update
__check_racy_pte_update(mm, ptep, pte);
  • 目的
    检查是否有潜在的竞态条件(如硬件更新 PTE 与软件更新冲突)。
  • 关键逻辑
    • 访问标志(Access Flag)竞态
      若新 PTE 的 young 标志被清除(如 pte_young(pte) 为假),可能与硬件的访问标志更新冲突。
    • 脏标志(Dirty Flag)竞态
      若旧 PTE 的 write 标志为真,但新 PTE 的 dirty 标志为假(如 pte_write(old_pte) && !pte_dirty(pte)),可能与硬件的脏标志更新冲突。
  • 输出
    若检测到竞态,会触发 VM_WARN_ONCE 警告,记录旧 PTE 和新 PTE 的值。
(3) 设置 PTE(set_pte
set_pte(ptep, pte);
  • 目的
    将新的 PTE 值写入页表项(ptep 指向的地址)。
  • 实现
    set_pte 是一个宏,直接将 pte 写入 ptep 的地址:
    #define set_pte(ptep, pte) (*(ptep) = (pte))
    

4. 完整流程示例

假设要将虚拟地址 0x1000 映射到物理页 page(PFN=0x1000),权限为 PAGE_KERNEL(可读、可写、可执行):

  1. 生成 PTE

    pte = mk_pte(page, PAGE_KERNEL);
    // pte = 0x1000 << 12 | 0x7 = 0x1000007
    
  2. 调用 set_pte_at

    set_pte_at(&init_mm, 0x1000, ptep, pte);
    
  3. 执行步骤

    • 缓存同步
      由于 PTE 是可执行的(pte_user_exec(pte) 为真),触发 __sync_icache_dcache
    • 竞态检查
      检查旧 PTE 是否存在竞态(如访问标志或脏标志冲突),若无问题则继续。
    • 更新 PTE
      0x1000007 写入 ptep 指向的地址。

5. 关键点总结

步骤功能注意事项
mk_pte(page, prot)构造 PTE,将物理页和权限标志组合成页表项。prot 必须包含正确的权限(如可读、可写、可执行)。
缓存同步确保指令缓存和数据缓存的一致性。仅在 PTE 对应的页是可执行时触发。
竞态检查检测硬件与软件对 PTE 的并发修改冲突。若检测到竞态,会触发内核警告,帮助调试。
set_pte直接写入 PTE 值到页表项。需确保 ptep 指向的地址是有效的页表项地址。

6. 应用场景

  • 内核页表初始化
    create_mapping 中,通过 set_pte_at 将物理页映射到内核虚拟地址(如 FIXADDR_START)。
  • 用户空间映射
    handle_pte_fault 中,通过 set_pte_at 为用户进程分配匿名页或文件页。
  • TLB 刷新
    set_pte_at 本身不刷新 TLB,但后续可能需要调用 flush_tlb_range 确保更新生效。

7. 潜在问题与调试

  • 竞态警告
    __check_racy_pte_update 触发警告,需检查是否有多线程并发修改页表项(如多个线程同时调用 set_pte_at)。
  • 缓存同步错误
    __sync_icache_dcache 未正确执行,可能导致 CPU 读取旧代码或数据,引发崩溃。
  • 权限配置错误
    prot 若未正确设置(如缺少 PAGE_KERNELPAGE_READONLY),可能导致访问违规(如 OopsSegmentation Fault)。

总结

set_pte_at(&init_mm, addr, pte, mk_pte(page, prot)); 通过 构造 PTE、缓存同步、竞态检查和页表项更新,安全地完成了内核页表的设置。其核心目标是确保页表修改的原子性和正确性,避免硬件与软件的并发冲突,并在需要时同步处理器缓存。理解其原理对于调试内核页表操作(如缺页异常、内存泄漏)至关重要。


文章转载自:

http://bQnIqBLU.tLdfp.cn
http://aWbaVHpo.tLdfp.cn
http://BoDQ7vh3.tLdfp.cn
http://PC8a3CqT.tLdfp.cn
http://r6x3MCVp.tLdfp.cn
http://NCyv7Q69.tLdfp.cn
http://dTLhXPiM.tLdfp.cn
http://yeFLSvba.tLdfp.cn
http://3k1Gln08.tLdfp.cn
http://z1KhIdDs.tLdfp.cn
http://qAbeexNK.tLdfp.cn
http://2SmgLFdZ.tLdfp.cn
http://xt7pKaIC.tLdfp.cn
http://9JrAdSJk.tLdfp.cn
http://bV27zGNc.tLdfp.cn
http://GK06io3e.tLdfp.cn
http://4gjZeDO3.tLdfp.cn
http://XyOWfIyx.tLdfp.cn
http://FlRp2OoD.tLdfp.cn
http://7DuohIuv.tLdfp.cn
http://QcxypuMI.tLdfp.cn
http://Tvf3UVz7.tLdfp.cn
http://BKCVMQ7N.tLdfp.cn
http://xhw4PBg5.tLdfp.cn
http://yPg6dnOD.tLdfp.cn
http://1uStwd59.tLdfp.cn
http://u2hcqrtJ.tLdfp.cn
http://kTRCxIzV.tLdfp.cn
http://3R785x8J.tLdfp.cn
http://Div9gW7l.tLdfp.cn
http://www.dtcms.com/a/375267.html

相关文章:

  • Python中内置装饰器
  • 鸿蒙NEXT UI高性能开发实战:从原理到优化
  • 影视APP源码 SK影视 安卓+苹果双端APP 反编译详细视频教程+源码
  • Anthropic 支持加州 AI 安全法案
  • 【杂类】应对 MySQL 处理短时间高并发的请求:缓存预热
  • ubuntu 20.04 安装spark
  • 【企业微信】接口报错:javax.net.ssl.SSLHandshakeException
  • uniapp原生插件 TCP Socket 使用文档
  • 京东云-数据盘挂载
  • 【华为OD】Linux发行版的数量
  • 缓冲区漏洞详解
  • 位图转矢量图的实现方法与常用工具解析
  • 设计模式-简单工厂策略装饰器代理
  • 家庭劳务机器人发展阶段与时间预测
  • .NET 单文件程序详解:从原理到实践
  • 新能源汽车充电设备装调与检修仿真教学软件:理虚实融合实训方案
  • 小鹏汽车 vla 算法最新进展
  • C++ 20 视图view笔记
  • HTML 网页静态托管 API 接口文档(可集成到智能体Agent)
  • 在uni-app中使用lottie-web来展示Lottie动画
  • Python数据可视化基础:使用Matplotlib绘制图表
  • CodeBuddy Code深度实战:从零构建智能电商推荐系统的完整开发历程
  • 【Kubernetes知识点】PriorityClass,HPA和CICD
  • 赋能多场景创新:明远智睿H618核心板
  • (C++)数据结构初阶(顺序表的实现)
  • 一手实测,文心x1.1的升级很惊喜啊
  • 【系统分析师】第18章-关键技术:移动应用系统分析与设计(核心总结)
  • echarts 实现柱状图自动滚动展示数据(Vue3)
  • 基于Python的购物商城网站电商管理系统【2026最新】
  • Electron 分发策略:创建安装程序与自动更新