1、pgd_addr_end

根据当前虚拟地址 addr 和目标结束地址 end,计算当前 PGD 项 能够覆盖的最大虚拟地址范围的结束地址 next。

  • 如果 addr 和 end 跨越多个 PGD 项(即 end 超出当前 PGD 项的地址范围),则返回当前 PGD 项的地址边界。
  • 如果 end 在当前 PGD 项的地址范围内,则返回 end。
  • 在建立页表映射时,内核需要逐个处理每个 PGD 项对应的地址范围。通过 pgd_addr_end,可以确定当前 PGD 项需要处理的地址范围 [addr, next),并更新 addr 为 next,以便处理下一个 PGD 项。

页表建立参考

do {next = pgd_addr_end(addr, end); // 计算当前 PGD 项的地址范围alloc_init_pud(pgd, addr, next, phys, prot, alloc); // 初始化 PUD 页表phys += next - addr; // 更新物理地址偏移
} while (pgd++, addr = next, addr != end);
  • 流程解释:
    • 循环处理每个 PGD 项:通过 do-while 循环,逐个处理 PGD 项。
    • 计算当前 PGD 项的地址范围:通过 pgd_addr_end 确定当前 PGD 项的地址范围 [addr, next)。
    • 初始化下级页表:调用 alloc_init_pud 为当前 PGD 项分配并初始化 PUD 页表。
    • 更新物理地址偏移:根据当前处理的地址范围大小(next - addr)调整物理地址 phys。
    • 移动到下一个 PGD 项:更新 addr 为 next,并继续处理下一个 PGD 项,直到 addr == end。

2、pgd_offset_k

pgd_offset_k(addr) 是 Linux 内核中用于 获取内核页全局目录(PGD)中对应虚拟地址 addr 的页表项地址 的宏。它是内核页表操作的核心宏之一,主要用于内核虚拟地址空间的映射初始化(如 early_fixmap_init)和页表建立(如 create_mapping)等场景。


1. 宏的定义与展开

#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
  • init_mm:内核的全局内存描述符(mm_struct),表示内核的地址空间(与进程的 mm 分离)。
  • pgd_offset(mm, addr):根据 mm 的 PGD 基地址和 addr 计算对应的 PGD 项地址。

进一步展开:

#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
  • (mm)->pgd:内核 PGD 的基地址(init_mm.pgd)。
  • pgd_index(addr):从 addr 中提取 PGD 项的索引。

2. pgd_index(addr) 的计算

#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
  • PGDIR_SHIFT:定义 PGD 项的位移量,决定 PGD 项覆盖的地址范围。例如:
    • 对于 ARM64(4 级页表),PGDIR_SHIFT = 39,每个 PGD 项覆盖 2^(48-39) = 512GB 地址空间。
  • PTRS_PER_PGD:PGD 项的数量(通常为 1 << (PGDIR_SHIFT - VA_BITS_SHIFT),例如 512 项)。
  • 作用:通过右移 addr 并掩码,提取 PGD 项的索引。

3. 典型使用场景

3.1 早期内核映射初始化(early_fixmap_init

在内核启动阶段,early_fixmap_init 函数会使用 pgd_offset_k 初始化固定映射区域(fixmap)的页表:

pgd_t *pgd = pgd_offset_k(FIXADDR_START);
__pgd_populate(pgd, __pa_symbol(bm_pud), PUD_TYPE_TABLE);
  • 作用:将 bm_pud(预分配的 PUD 页表)的物理地址写入 PGD 项中,建立从 FIXADDR_STARTbm_pud 的映射。
  • 后续步骤:通过 pud_offsetpmd_offsetpte_offset 逐级填充页表。
3.2 通用页表建立(create_mapping

在内核中,create_mapping 函数会通过 pgd_offset_k 遍历虚拟地址范围并建立页表:

pgd_t *pgd = pgd_offset_k(virt_addr);
do {next = pgd_addr_end(addr, end);alloc_init_pud(pgd, addr, next, phys, prot);phys += next - addr;addr = next;
} while (pgd++, addr != end);
  • 作用:逐个处理每个 PGD 项的地址范围,初始化下级页表(PUD → PMD → PTE)。

4. ARM64 架构示例

假设:

  • addr = 0xffff7ffffabfe000FIXADDR_START
  • init_mm.pgd = 0xffff800000ef0000
  • PGDIR_SHIFT = 39PTRS_PER_PGD = 512
4.1 计算 pgd_index(addr)
pgd_index(addr) = (0xffff7ffffabfe000 >> 39) & 0x1ff = 0xff
  • 解释addr 的高 9 位(0x1ff)即为 PGD 项的索引。
4.2 计算 pgd_offset_k(addr)
pgd_offset_k(addr) = init_mm.pgd + 0xff * sizeof(pgd_t)
  • ARM64 中 pgd_t 占 8 字节,因此:
    pgd_offset_k(addr) = 0xffff800000ef0000 + 0xff * 8 = 0xffff800000ef07f8
    
  • 结果:这是 addr 在内核 PGD 中对应项的虚拟地址。

5. 关键点总结

  1. 目的

    • 快速定位内核虚拟地址 addr 在 PGD 中的项地址。
    • 为后续页表建立(如 PUDPMDPTE)提供起点。
  2. 层级关系

    • pgd_offset_k 属于页表操作宏的第一级(PGD),后续通过 pud_offsetpmd_offsetpte_offset 逐级展开。
  3. 架构依赖

    • PGDIR_SHIFTPTRS_PER_PGD 的定义依赖于架构(如 ARM64、x86)和页表层级(4 级或 2 级)。
  4. 应用场景

    • 早期内核映射(fixmapioremap)。
    • 动态内存映射(vmallocioremap)。
    • 设备树(DTB)的加载(通过 fixmap 映射物理地址)。

6. 常见问题

Q1:为什么 pgd_offset_k 使用 init_mm
  • 原因:内核地址空间是全局的,所有进程共享同一个内核 PGD(init_mm.pgd)。通过 init_mm 可直接访问内核页表。
Q2:如何验证 pgd_offset_k 的正确性?
  • 调试方法:在 early_fixmap_init 中打印 pgd_offset_k(addr) 的值,并检查其是否对应预期的 PGD 项地址(如通过 pr_err 输出)。
Q3:ARM64 中为何需要乘以 8?
  • 原因:ARM64 的每个 PGD 项占用 8 字节(64 位),因此索引 0xff 对应的偏移量为 0xff * 8 = 0x7f8

7. 扩展:页表层级划分(以 ARM64 为例)

层级地址位移页表项大小映射范围
PGDpgd_index(addr)>> 398 字节512GB
PUDpud_index(addr)>> 308 字节1GB
PMDpmd_index(addr)>> 218 字节2MB
PTEpte_index(addr)>> 128 字节4KB

总结

pgd_offset_k(addr) 是内核页表操作的基础,通过计算虚拟地址 addr 在 PGD 中的项地址,为后续的页表建立提供起点。理解其工作原理对于调试内核内存管理、分析页表初始化流程至关重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95965.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95965.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/95965.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XR数字融合工作站赋能新能源汽车专业建设的创新路径

XR数字融合工作站作为集PC、VR、MR技术于一体的软硬件集成平台&#xff0c;凭借其多维交互、虚实融合、智能管理等特性&#xff0c;为新能源汽车专业的教学改革与创新提供了全新解决方案。一、教学场景革新&#xff1a;构建沉浸式、互动化学习环境XR数字融合工作站通过多形态拼…

C语言通用链表终章:优雅的收尾 - 清空与销毁

各类资料学习下载合集 ​https://pan.quark.cn/s/8c91ccb5a474​ 经过前面的学习,我们已经从零构建了一个功能强大的通用链表,它能自如地进行节点的插入和删除。我们的“数据火车”已经可以驰骋在内存的世界里。然而,旅途终有终点,当火车完成任务后,如何安全、彻底地让…

MATLAB R2025a安装配置及使用教程(超详细保姆级教程)

文章目录前言什么是MATLAB&#xff1f;了解这款数据分析利器matlab安装前准备工作MATLAB R2025a下载完整MATLAB R2025a安装步骤MATLAB进阶应用技巧前言 全网最新最全的MATLAB R2025a安装教程来了&#xff01;2025年版本完整图文指南&#xff0c;包含软件下载、详细安装、密钥激…

在Mybatis plus中如何使用自定义Sql

在演示UpdateWrapper的案例中&#xff0c;我们在代码中编写了更新的SQL语句&#xff1a;Test void testUpadateWrapper(){List<Long> ids List.of(1L,2L,4L);//生成SQLUpadateWrapper<User> wrapper new UpdateWrapper<User> ().setSql("balance balan…

Deepoc科技之暖:智能助盲设备如何为视障家人点亮生活

作为一名视障人士的家属&#xff0c;我们或许都经历过这样的时刻&#xff1a;看着亲人在书架前摸索&#xff0c;却无法独自获取文字信息&#xff1b;担心他们外出时遇到障碍物或交通危险&#xff1b;心疼他们因找不到日常物品而不得不一次次求助。这些细微的日常困境&#xff0…

大模型食材识别技术革新:AI重构精准营养管理

随着健康意识的提升&#xff0c;饮食管理需求激增&#xff0c;但传统手动记录易出错、效率低。大模型食材识别技术的突破&#xff0c;让AI通过多模态输入精准识别食材种类与重量&#xff0c;结合营养数据库&#xff0c;系统可快速生成营养报告&#xff0c;实现从“经验驱动”到…

使用 Altair RapidMiner 将机器学习引入您的 Mendix 应用程序

Altair RapidMiner 使机器学习更加容易&#xff1a;无论您喜欢使用 Python 编码&#xff0c;还是在 Workflow Studio 中进行可视化工作&#xff0c;Altair AI Cloud 都能为团队提供快速构建和部署 ML 模型的工具。 将机器学习与 Mendix 集成很简单&#xff1a;通过 Mendix 的低…

EasyExcel:快速读写Excel的工具类

EasyExcel&#xff1a;快速读写Excel的工具类 项目介绍 ​EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。 他能让你在不用考虑性能、内存的等因素的情况下&#xff0c;快速完成Excel的读、写等功能。 pom地址 ‍ <!--exel--> <depe…

WSL Ubuntu Docker 代理自动配置教程

WSL Ubuntu Docker 代理自动配置教程 WSL Ubuntu Docker 代理自动配置教程 背景说明 在 WSL2 环境下使用 Docker 时&#xff0c;由于网络环境限制&#xff0c;经常需要通过 Windows 主机上的代理来访问 Docker Hub。但每次 Windows 重启后&#xff0c;WSL 获取到的主机 IP 地址…

踩坑实录:Django继承AbstractUser时遇到的related_name冲突及解决方案

一、问题现象分析 咱们在用Django开发时&#xff0c;有时候需要扩展用户模型&#xff0c;就会去继承AbstractUser。但这么做的时候&#xff0c;要是没处理好groups和user_permissions这两个多对多字段的反向查询名称&#xff0c;就会遇到这样的报错&#xff1a;主要就是这种错误…

push pop 和 present dismiss

push/pop 和 present/dismiss 文章目录push/pop 和 present/dismiss前言push / poppresent普通的present多层present多层present后的父子关系问题多层弹出会遇到的问题showViewController 和 showDetailViewControllershowViewControllershowDetailViewControllerdismiss模态化…

服务器异常负载排查手册 · 隐蔽进程篇

适用范围 适用于 Linux 3.10 生产环境&#xff0c;发现 load 高但用户态 CPU 接近 0 % 的场景。1. 现场冻结目标&#xff1a;在 rootkit 干预前保存易失数据。#!/bin/bash # freeze.sh TS$(date %s) mkdir -p /srv/ir/${TS} cd /srv/ir/${TS}# 1.1 进程树&#xff08;busybox 静…

2024理想算法岗笔试笔记

要理解指令微调&#xff08;Instruction Tuning&#xff09;&#xff0c;需要先将其置于大语言模型&#xff08;LLM&#xff09;的训练框架中 —— 它并非模型训练的起点&#xff0c;而是针对 “让模型更懂人类需求” 的关键优化步骤。简单来说&#xff0c;指令微调是通过让模型…

Oracle 11g离线安装依赖包完整解决方案

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Oracle 11g是一款广泛使用的关系型数据库管理系统&#xff0c;在离线环境下安装时需依赖多个系统库和工具。本“oracle11g依赖包”压缩文件包含了在CentOS 7.7上安装Oracle 11g可能缺失的关键依赖RPM包&#xf…

VBA数据结构选型:效率差5倍的生死抉择

VBA性能生死局&#xff1a;Dictionary与Collection效率差5倍&#xff01;90%开发者用反血亏“你以为Collection是VBA的‘轻量级选手’&#xff1f;大错特错&#xff01;实测数据显示&#xff1a;在10万级数据循环中&#xff0c;Dictionary的查询速度比Collection快5倍&#xff…

电机控制(四)-级联PID控制器与参数整定(MATLABSimulink)

PID算法 普通PID&#xff08;Proportional-Integral-Derivative&#xff09; 通过比例&#xff08;P&#xff09;、积分&#xff08;I&#xff09;和微分&#xff08;D&#xff09;三项来进行控制 比例项&#xff08;P&#xff09;&#xff1a;根据当前误差&#xff08;目标值…

数据结构深度解析:二叉树的基本原理

在数据结构体系中&#xff0c;树是一种重要的非线性层次结构&#xff0c;它通过 “节点” 与 “边” 的连接关系&#xff0c;模拟了现实世界中树的分支结构&#xff0c;能够高效地解决数据的查找、插入、删除等问题。而二叉树作为树结构中最简单、应用最广泛的类型&#xff0c;…

【React】Ant Design 5.x 实现tabs圆角及反圆角效果

需要实现的效果实现思路 利用tab页的before和after属性&#xff0c;添加tab页前后的圆弧属性&#xff0c;同时使用tab页的shadow阴影填充右下角的圆弧空缺部分。<TabsonChange{onChange}type"card"items{getTabItems()}/>.ant-tabs-nav{margin: 0;.ant-tabs-na…

WordPress过滤文章插入链接rel属性noopener noreferrer值

WordPress过滤文章插入链接rel属性noopener noreferrer值在保存文章的时候&#xff0c;WordPress会自动过滤文章内容中的链接&#xff0c;具有target属性的链接会自动添加rel"noopener noreferrer"&#xff0c;该属性是为了预防跨站攻击&#xff0c;站内链接似乎没有…

make_shared的使用

目录 1. make_shared 的基本概念 基本用法 2. 引入 make_shared 的主要原因 2.1 解决传统构造方式的问题 2.2 标准委员会的动机 3. make_shared 的核心优势 3.1 性能优势&#xff08;最重要优点&#xff09; 内存分配优化&#xff1a; 性能提升表现&#xff1a; 3.2 异…