内核启动过程分析
Posted 正在起飞的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内核启动过程分析相关的知识,希望对你有一定的参考价值。
1、uboot引导内核启动
2、找到内核的入口
内核是从汇编代码开始运行,以arm架构的芯片为例,arch/arm/kernel/head.S的ENTRY(stext)处就是起始代码。参考博客:《如何快速确定程序的入口》。
3、汇编代码阶段
3.1、设置成SVC模式并禁止终端
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode and irqs disabled
调用setmode去设置CPSR寄存器的中断位和模式位。
3.2、检查内核是否支持当前CPU型号
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=0)?
beq __error_p @ yes, error 'p'
参考博客:《内核启动过程中对CPU型号的确认》。
3.3、检查内核是否支持当前机器,也就是开发板
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
参考博客:《内核启动过程中机器码的确定》。
3.4、检查uboot传参tag参数
bl __vet_atags
参考博客:《内核中对uboot传参tags的校验》。
3.5、创建临时页表
bl __create_page_tables
3.6、跳转执行__switch_data函数
ldr r13, __switch_data
__switch_data:
.long __mmap_switched
.long __data_loc @ r4
······
__switch_data汇编函数在分析启动过程中没什么特别需要关注的,直接跳转到__mmap_switched函数。
3.7、跳转执行__mmap_switched函数
__mmap_switched:
adr r3, __switch_data + 4
······
b start_kernel
ENDPROC(__mmap_switched)
__mmap_switched函数就是调用start_kernel函数,跳转到C语言继续进行内核启动。
3.8、执行start_kernel函数
进入C语言阶段继续启动内核,start_kernel函数里是各模块的初始化,下面只对其中常用的模块进行介绍。
4、C语言阶段
4.1、打印内核版本信息:
const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\\n";
printk(KERN_NOTICE "%s", linux_banner);
linux_banner字符数组保存的是内核的版本等相关信息。在定义linux_banner字符数组时,把那些宏定义包含进去。
4.2、解析uboot传递的tag参数、CPU信息、机器信息
setup_arch(&command_line);
把uboot传给内核的启动参数保存到command_line变量中;
4.3、解析uboot传递的cmdline
printk(KERN_NOTICE "Kernel command line: %s\\n", boot_command_line);//打印command_line
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
4.4、跳转到rest_init()函数,执行后续的初始化
(1)rest_init()函数调用kernel_thread()函数创建init进程和kthreadd进程;
(2)rest_init()函数最后调用cpu_idle()函数变成0号进程;
(3)内核启动结束;
以上是关于内核启动过程分析的主要内容,如果未能解决你的问题,请参考以下文章
20135239 益西拉姆 linux内核分析 跟踪分析Linux内核的启动过程