Linux源码分析-内核启动过程

1. 启动入口

通过链接脚本arch/arm/kernel/vmlinux.lds可以找到内核的入口函数,通过ENTRY(stext)可以知道内核进入的第一个接口为stext接口,由于初始化部分的代码是与架构相关的,所以在不同架构中都有对stext接口的实现,例如查看arm64架构的初始化流程,则进入arch/arm64/kernel/head.S文件,stext接口的实现如下: Linux源码分析-内核启动过程_第1张图片
该接口实现了内核启动的汇编阶段,主要实现的功能如下:
a) 将bootloader传递过来的参数保存在全局数组boot_args中;
b) 判断是否需要将处理器异常级别降到级别1;
c) 创建页表映射;为开启处理器的内存管理单元做准备、初始化处理器;为主处理器开启内存管理单元,搭建C语言执行环境,进入C语言部分的入口函数start_kernel。

2. C语言实现高级功能

在head.S文件__primary_switch接口中,该接口为主处理器开启内存管理单元,然后进入__primary_switched接口搭建C语言执行环境,进入C语言部分的入口函数start_kernel。 start_kernel接口位于init/main.c文件中,接口进行了一系列的初始化,包括内存初始化、uboot参数解析、调度器初始化等,最后进入rest_init接口,该接口也位于main.c文件,实现如下:
Linux源码分析-内核启动过程_第2张图片
接口中调用kernel_thread创建kernel_init进程和kthreadd进程,kernel_init进程就是大名鼎鼎的init进程,init进程的PID为1。init进程一开始是内核进程 (也就是运行在内核态 ),后面init进程会在根文件系统中查找名为“ init”这个程序,这个“ init”程序处于用户态,通过运行这个 init”程序,init进程就会实现从内核态到用户态的转变。kthreadd为内核进程,此进程的 PID为 2。kthreadd进程负责所有内核进程的调度和管理。
kernel_init接口中执行用户程序的过程如下:
Linux源码分析-内核启动过程_第3张图片
接口中首先加载命令行传进来的init程序,execute_command是一个全局的char指针变量,值由bootargs使用中使用“ init=xxxx”方式传入,比如 init=/linuxrc”表示根文件系统中的 linuxrc就是要执行的用户空间 init程序。
如果执行失败则挨个运行/sbin/init、/etc/init、/bin/init、/bin/sh,如果有一个成功的就启动成功,每一个成功的就启动失败,内核通过控制台打印出kernel_panic的严重错误。
至此,内核的大致启动流程就结束了,详细的启动请根据内核代码进行分析 查看。

你可能感兴趣的:(#,内核启动,内核)