Linux内核6.6 内存管理 (17)内核镜像区和线性映射区

内核镜像区和线性映射区

map_kernel中所有虚拟地址均 direct_map_end(0xffff800000000000),属于内核镜像专属虚拟区域,不在线性映射区内。内核正常运行时,CPU 直接访问这些虚拟地址执行代码(text 段)、读取数据(rodata、data 段),是内核 “工作时” 的主地址

线性映射区是内核用于直接访问物理内存的虚拟地址区域,由 map_mem 函数负责映射

物理地址到内核镜像区 __phys_to_kimg

https://elixir.bootlin.com/linux/v6.6/source/arch/arm64/include/asm/memory.h#L310

map_kernel的地址计算:(通过 kimage_voffset 转换)

内核镜像区的虚拟地址与物理地址通过 kimage_voffset 关联(物理地址 = 虚拟地址 - kimage_voffset):

以 text 段为例:

虚拟起始 = 0xffff800080010000

物理起始 = 0xffff800080010000 - 0xffff7ffffcc00000 = 0x83410000(与日志中 Kernel text+rodata segment range (physical) 起始一致)。

整个内核镜像的物理地址范围:0x83410000 ~ 0x84ef0000(text+rodata 段),位于物理内存中(> PHYS_OFFSET 0x80000000)。

该虚拟地址范围:所有虚拟地址均 > direct_map_end(0xffff800000000000),属于内核镜像专属虚拟区域,不在线性映射区内。

物理地址到线性映射区 __phys_to_virt

映射规则(物理地址 ↔ 虚拟地址)

通过线性映射公式转换:虚拟地址 = 物理地址 - PHYS_OFFSET + PAGE_OFFSET

验证:物理起始 0x83410000 对应的线性虚拟地址:

0x83410000 - 0x80000000 + 0xffff000000000000 = 0xffff000003410000(与日志完全一致)。

该虚拟地址范围:由 PAGE_OFFSET(起始)和 direct_map_end(结束)界定:0xffff000000000000 ≤ 虚拟地址 < 0xffff800000000000

完整日志

这里还是建议先把kaslr关掉,不然PHYS_OFFSET每次都会显示不同的地址,这里我们可以看到,物理地址偏移是0x80000000,这个正常就是设备树里memory的内容,应该是固定的

表格对照

__phys_to_virt 用于将任意物理地址转换为线性映射区的虚拟地址,供内核管理物理内存;

__phys_to_kimg 用于将内核镜像的物理地址转换为内核镜像区的虚拟地址,供内核访问自身代码和数据。

同样也是这两个区域的功能对照

#嵌入式笔面经分享##嵌入式转岗的难度怎么样##嵌入式##嵌入式软开#
全部评论

相关推荐

10-02 08:48
门头沟学院 Java
点赞 评论 收藏
分享
点赞 评论 收藏
分享
昨天 01:06
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务