🗒️linux内核源码解析03–启动代码分析之主内核页表创建
2024-7-28
| 2024-11-4
字数 2266阅读时长 6 分钟
type
status
date
slug
summary
tags
category
icon
password
URL

Linux初始化过程页表建立

Linux初始化过程,会依次建立如下页表映射:
  1. 恒等映射:页表基地址idmap_pg_dir;
  1. 粗粒度内核镜像映射:页表基地址init_pg_dir;
  1. fixmap映射:页表基地址为init_pg_dir,待paging_init之后为swapper_pg_end;
  1. 细粒度内核镜像映射:页表基地址为swapper_pg_dir;
  1. 线性映射: 页表基地址为swapper_pg_dir;
  1. 用户空间页表映射:页表基地址task->mm->pgd;
上篇解析 "fixmap映射" , 这里来解析主内核页表的创建, 包括"4.细粒度内核镜像映射"和"5.线性映射";
创建完固定映射后,会初始化物理页面分配器,即初始化伙伴系统;有了物理页面分配器,内核主页表就可以建立动态映射页表:
页面分配器这里略去,先来看主内核页表的建立,分两部分:

建立内核的细粒度映射

map_kernel()函数

将内核的每个段,分别建立页表

map_kernel_segment函数

为内核的段建立动态映射

__create_pgd_mapping函数

建立页表

动态分配页表

页表建立过程很简单,就不过多啰嗦了,这里标记两点:1.由于页面分配器已经初始化完,这里可以动态分配页表;(内核启动到这里之前,都是静态页表,即页表都是固定页面);2.动态分配的页表,拿到的是物理地址,要继续向下一级页表遍历,必须将物理地址转化为虚拟地址, CPU才能正确访问;
这样,内核镜像的各个段,就全部做了动态映射,后面访问,就不再依赖于固定映射;
但是pgd一级页表基地址,还是用的固定地址swapper_pg_dir, 内核页表建立后,需要将页表基地址更新到init进程的mm_struct结构体;
现在内核镜像本身可以自由访问了,但物理内存的其他区域,依然无法访问,为方便内核自由访问所有物理内存,Linux做了一个线性映射,

线性映射

将物理内存全部线性映射到虚拟地址段(仅做一个偏移),后续在内核空间可以直接用偏移地址访问整个物理内存;

线性映射核心函数map_mem()

__map_memblock

实际建立页表映射过程过程与细粒度大致相似
至此,Linux内核主页表创建完毕。
 
 
  • linux kernel
  • 必看精选
  • linux内核源码解析02–启动代码分析之固定映射linux源码解析05–ioremap原理
    Loading...