Linux内核启动流程:
先找到Linux的入口地址,入口地址在链接脚本vmlinux.lds中定义
启动前在启动之前,确保MMU,D-cache,I-cache关闭,R0寄存器置空,R1寄存器存入机器ID,用于标识硬件平台型号,R2寄存器存放设备树指针地址
阶段一:汇编层初始化(检查硬件兼容性、准备内存映射环境、为 C 语言运行铺路)
具体步骤:
1、确保 CPU 处于SVC 模式(超级用户模式,拥有最高权限),并关闭所有中断(避免初始化被中断打断),为后续操作提供稳定环境。
2、读CPU ID,获取当前CPU硬件标识,在kernel预设的proc数组中匹配CPU,匹配成功的话,就返回该CPU的procinfo结构体(MMU flags、缓存操作函数),存入R5寄存器中。
3、验证R2寄存器中的dtb合法性,如果出现异常,则后续内核可能无法获取硬件资源。
4、创建临时页表,为后续 “使能 MMU” 做准备(MMU 需要页表实现 “物理地址→虚拟地址” 映射),仅映射内核代码段、数据段和关键硬件寄存器地址,无需完整映射所有内存(后续会扩展)
5、最终调用start_kernel,调用(CPU结构体)procinfo中预设的 CPU 初始化函数(如缓存控制器配置、MMU 准备),使能 MMU,CPU 开始使用虚拟地址,MMU 使能完成后,自动跳转到r13存储的__mmap_switched,进入 C 层初始化。
阶段二:C 语言层内核层初始化
start_kernel是内核 C 层的 “总入口”,相当于内核的 “main 函数”,会调用数十个初始化函数,完成:
1、内存管理子系统初始化(如页表扩建、内存分配器buddy初始化);
2、中断控制器初始化(GIC初始化,使能中断响应)
3、进程调度器初始化()
4、虚拟文件系统初始化(VFS)(为后续挂在根文件系统做准备)
5、调用rest_init,进入“核心进程初始化”阶段
阶段三:核心进程创建
rest_init的核心目标是 “创建 Linux 系统的 3 个核心进程”,奠定系统进程模型
1、启动 RCU 锁调度器(Read-Copy-Update,内核并发控制机制),为多核环境下的进程同步提供支持。
2、创建PID=1 的 init 进程(kernel_init),核心任务:完成设备驱动初始化、挂载根文件系统、启动用户空间的 init 程序。
3、创建PID=2 的 kthreadd 进程,负责创建和调度所有内核线程(如 I/O 线程、定时器线程)。
4、初始化并启动idle 进程(空闲进程)(当前进程,PID=0),CPU 空闲时运行的 “空闲进程”,优先级最低,仅在无其他进程可调度时执行。
阶段四、衔接用户空间,kernel_init函数
kernel_init是 PID=1 的 init 进程的核心逻辑,目标是 “完成内核到用户空间的过渡”,分为 “前期初始化” 和 “启动用户空间 init 程序” 两部分:
前期初始化:
1、wait_for_completion(&kthreadd_done) 等待 kthreadd 进程完全就绪,避免 init 进程创建内核线程时 kthreadd 未初始化。
2、smp_init() → sched_init_smp() 初始化 SMP(对称多处理):唤醒多核 CPU(如 ARM Cortex-A7 的其他核心);初始化多核进程调度逻辑,确保多核心能协同工作。
3、调用driver_init,初始化内核驱动模型子系统(如 platform 总线、USB 总线),遍历并初始化所有已注册的设备驱动(如 GPIO、UART、存储控制器驱动),让硬件具备工作能力。
4、初始化系统控制台:打开/dev/console(由 Bootloader 的bootargs指定,如console=ttymxc0,115200对应串口 1),文件描述符为0(标准输入);
5、挂载根文件系统:读取bootargs中的root参数(如root=/dev/mmcblk1p2表示根文件系统在 EMMC 分区 2);初始化存储设备(如 EMMC、SD 卡),挂载根文件系统(如 ext4 格式),让内核能访问用户空间的文件。
启动用户空间 init 程序:init 进程的最终目标是启动用户空间的init程序(系统第一个用户进程)

1万+

被折叠的 条评论
为什么被折叠?



