内核代码启动流程:内核首先运行arch/arm/kernel/head.S
第一阶段
Head.s函数
1. 确认CPU ID
S3C2410 CPU ID为0x41129200
如果CPU ID & 掩码 = 0x41009200 ,则审核通过
如果错误会发生“p error”
2. 确认开发板型号
在arch/arm/tools/mach-types 记录了各个arm开发板的编号,对应三星的smdk2410的编号为193
如果匹配会发生“a error”
3. 建立页表
4. 启动mmu
5. 清bss段,复制数据段,设置栈指针(为调用C函数做准备)
第二阶段
6. 调用start_kernel函数init/main.c(内核的第一个C函数,详细调用关系见附录1)
(1)打印版本信息
(2)setup_arch和setup_commndline(处理uboot传入内核的启动参数)
(3)console_init (初始化控制台)
(4)其他系列初始完成后,调用reset_init
7. rest_init函数中调用关系如下
kernel_init函数
->prepare_namespace函数
-> mount_root()函数 //挂接根文件系统
->(1)打开三个文件(标准输入,标准输出,标准出错)open(dev/consle) sys_dup(0) sys_dup(0)
->Init_Post函数 //执行应用程序
8. init_post函数
(2)运行第一个应用程序(一般是linuxrc ,而linuxrc是指向busybox的链接,所以其实运行的第一个程序就是busybox,见附录3
9. Busybox的运行
busybox调用的第一个函数就是init_main,在这个函数中完成了三项工作:
1应用程序配置文件读取
2.解析应用程序配置文件
3.执行用户应用程序
详细的调用关系如下:
Busybox->init_main
->Parase_inittab
->File=fopen(INITTAB,”r”);//打开配置文件,见附录2
->执行一些列new_init_action函数(1.创建一个init_action结构2.把这个结构放入init_action_list链表,这个时候只是得到链表,并没有开始执行)
->run_actions(SYSINIT)//执行sysint类的程序
->run_actions(WAIT)
->run_actions(ONCE)
While(1)
{
-> run_actions(RESPAWN)
-> run_actions(ASKFIRST)
}//注意:其他类型的执行时机是当用户给init进程发送信号时,用信号处理函数调用的(例如shutdown)
至此内核启动完毕,等待用户输入#......................................................................
OYEAH!
从内核的启动过程分析得出,最小的根文件系统必须包含:
1. dev/console dev/null
2. 来源于busybox的sbin/init
3. 应用程序配置文件/etc/inittab
4. 配置文件指定的应用程序(例如bin/sh)
5. c库的支持
linuxrc ->/etc/inittab
->/etc/init.d/rcs
->/usr/etc/rc.local //可以在里面定义用户应用程序
->/etc/profile/
附录1start_kernel相关调用关系:*************************************************
图片无法上传
附录2************************************************************************
在inittab中规定了那些应用程序可以执行,存放了各个应用程序的配置文件,格式如下:
Id:runlevel:action:process
其中的action:代表程序执行的时机
Process:代表应用程序或脚本
在内核代码中规定了默认的配置文件,解析后如下:
图片无法上传
而执行时机的话有以下几种
图片无法上传
附录3 initpost关于调用linuxrc的代码********************************
if (execute_command) {
run_init_process(execute_command);
printk(KERN_WARNING"Failed to execute %s. Attempting"
"defaults.../n",execute_command);
}
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
在bootagrs中设定了init=linuxrc,所以一般只执行run_init_process(execute_command);,后面的就没有机会执行了,如果没有指定execute_command,那么才依次执行后面的run_init_process,如果全部没有找到,内核就Panic啦!