作者:GWD 时间:2019.8.1
一、课程内容
1、独立的文件系统 (Linux) SHELL
2、Linux种对文件系统的支持
3、文件系统的层次
4、熟悉每个文件夹里面都有大致什么东西
5、分析文件系统的工作流程(起点: 目的:可以运行其他应用程序,可以响应用户的命令)
二、起点分析:linux-2.6.22.6分析
1、内核的目的是运行kernel_init然后在kernel_init挂载根文件系统;
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console.\n");
(void) sys_dup(0);
(void) sys_dup(0);
打开控制台做为标准输入 复制了 标准输出 复制了标准错误
2、接下来涉及到了代码段的知识,如果执行了run_init_process就不会再执行printk了。相当于之前的switch,切换到下一个进程。若果出错了会一次执行779-782行,这些是在根文件系统中的。如果这些也没有就启动不了了,之前在移植内核时候遇到过这样的情况就是这样发生的。
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"); //都是由busybox所提供的
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
//如果当前的文件系统中没有可执行的初始化程序 ,则内核启动文件系统失败
panic("No init found. Try passing init= option to kernel.");
3、在init_setup函数中给全局变量赋值,我们接下来看看谁调用了init_setup
解析:
__setup(“init=”, init_setup);
__setup_param(“init=”, init_setup, init_setup, 0)
static char __setup_str[] __initdata = “init=”;
static struct obs_kernel_param _setup
attribute_used
attribute((section(".init.setup")))
attribute((aligned((sizeof(long)))))
= { _setup_str, init_setup, 0 }
也就是在.init.setup这个段中放入obs_kernel_param这样的结构体,且early=0,这个段在lds中被定义。
4、tagglist—》内存参数、硬盘参数、视频参数、命令参数是怎么解析的?
1)、early = 0时
2)、early = 1时
梳理一下:UBOOT传入了很多的参数 tagglist,被解析为多个setup的段—存放在.init.setup的代码段中,形式为CMD(字符串),命令对应的处理函数在两个函数中,obsolete_checksetup (处理eraly为0的)、do_early_param(处理eraly不为0的)。进行了所有存放在.init.setup代码段的命令执行针对各种setup段的CMD进行全局变量的赋值
5、再举例看一下execute_command全局变量在哪里被赋值
也是在setup函数中被赋值,一旦绑定setup宏定义就被创建obs_kernel_param结构体
这个结构体叫rdinit_setup被放入了.init.setup段中,在start_kernel的parse_args,中被执行。解析参数函数parse_args又调用unknown_bootoption函数,unknown_bootoption又调用obsolete_checksetup
小结:tagglist---》内存参数、硬盘参数、视频参数、命令参数
parse_args("Booting kernel", static_command_line, __start___param,__stop___param - __start___param,&unknown_bootoption);
unknown_bootoption
obsolete_checksetup
static int __init obsolete_checksetup(char *line) //early为0的参数处理、
else if (!p->setup_func) {
printk(KERN_WARNING "Parameter %s is obsolete,"" ignored\n", p->str);
return 1;
} else if (p->setup_func(line + n))
return 1;
static int __init do_early_param(char *param, char *val)// early不为0的参数处理
for (p = __setup_start; p < __setup_end; p++) {
if (p->early && strcmp(param, p->str) == 0) {
if (p->setup_func(val) != 0)
6、execute_command是UBOOT传入的,以 init=xxxxx的参数UBOOT传入的CMD参数。
init=linurc、execute_command=linuxrc
init=
if (linuxrc)
{
run_init_process(linuxrc); 内核切换到了文件系统中进行Linuxrc应用程序的运行
}
文件系统从此开始运行:
三、在文件系统busybox中怎么运行的
1、在busybox中搜索linuxrc看看在哪里被调用
2、init中首先设置了一些信号,为什么呢?因为不论是shell命令,还是人为的用户程序先接触的都是文件系统,只有通过系统调用才可以接触到内核。Signal是系统内核的库函数,接触到信号后就调用系统库函数。这些程序里面基本都有一个run_action这个程序。这个程序是做什么的在下一节说。
3、
int init_main(int argc, char **argv)
/* Set up sig handlers -- be sure to
* clear all of these in run() */
signal(SIGHUP, exec_signal);
signal(SIGQUIT, exec_signal);
signal(SIGUSR1, shutdown_signal);
signal(SIGUSR2, shutdown_signal);
signal(SIGINT, ctrlaltdel_signal);
signal(SIGTERM, shutdown_signal);
signal(SIGCONT, cont_handler);
signal(SIGSTOP, stop_handler);
signal(SIGTSTP, stop_handler);
4、作业:认真理解Linux2.26参数解析的过程。找到5个类似于execute_command变量解析形式的全局变量,分析明白。