linux内核与文件系统的衔接关系
Posted 西邮菜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核与文件系统的衔接关系相关的知识,希望对你有一定的参考价值。
一、如何从内核跳转到busybox,和文件系统的工作流程
在创建根文件系统的时候,如果使用Busybox的话,只需要在/dev目录下创建必要的设备节点,在/etc目录下增加一些配置文件即可,当然,如果Busybox使用动态链接,那么还需要再/lib目录下包含库文件。下面是Busybox源码目录结构图:
if (execute_command)
run_init_process(execute_command);
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
如果设立了execute_command变量则跳转到他的代码中,这里execute_command=linuxrc,则跳转到busybox上,其实linuxrc与/sbin/init都指向了busybox文件系统。现在开始跑文件系统的代码。进入的是init_main函数。
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);
console_init();
parse_inittab();
run_actions(SYSINIT);
run_actions(WAIT);
run_actions(ONCE);
while (1)
run_actions(RESPAWN);
run_actions(ASKFIRST);
sleep(1);
wpid = wait(NULL);
while (wpid > 0)
for (a = init_action_list; a; a = a->next)
if (a->pid == wpid)
a->pid = 0;
message(L_LOG, "process '%s' (pid %d) exited. "
"Scheduling it for restart.",
a->command, wpid);
wpid = waitpid(-1, NULL, WNOHANG);
二、__setup宏分析原理
下面是 __setup宏分析,__setup这条宏在Linux Kernel中,使用最多的地方就是定义处理Kernel的启动参数 的函数及数据结构,宏定义如下:
#define __setup(str, fn) \\
static char __setup_str_##fn[] __initdata = str; \\
static struct obs_kernel_param __setup_##fn \\
__attribute_used__ \\
__attribute__((__section__(".init.setup"))) \\
= __setup_str_##fn, fn
init.h:
struct obs_kernel_param
const char *str;
int (*setup_func)(char *);
;
vmlinux.lds.S:
. = ALIGN(16);
__setup_start = .;
.init.setup : *(.init.setup) .init.setup段的位置。
__setup_end = .;
比如:__setup("init=", init_setup);被解析后就是:
#define __setup(init=,init_setup ) \\
static char __setup_str_ __initdata = “init=”; \\
static struct obs_kernel_param __setup_ \\
__attribute_used__ \\
__attribute__((__section__(".init.setup"))) \\
= __setup_str_, fn
初始化内容为"root=",由于该变量用 __initdata修饰,它将被放入.init.data输入段;另一变量是结构变量__setup_str,其类型为 struct obs_kernel_param, 该变量被放入 输入段.init.setup中。
通过__setup宏定义obs_kernel_param结构变量都被放入.init.setup段中,这样一来实际是使.init.setup段变成一张表,Kernel在处理每一个启动参数时,都会来查找这张表,与每一个数据项中的成员str进行比较,如果完全相同,就会调用该数据项的函数指针成员setup_func所指向的函数(该函数是在使用__setup宏定义该变量时传入的函数参数),并将启动参数 如root=后面的内容 传给该处理函数。
execute_command是UBOOT传入的,以 init=xxxxx的参数UBOOT传入的CMD参数。
init=linurc、execute_command=linuxrc。最后程序跳转进busybox文件系统。(uboot传来init=linurc,我们的“init=”经过段中表查找得出linuxrc,所以最终execute_command=linuxrc)
梳理一下:UBOOT传入了很多的参数 tagglist,被解析为多个setup的段—存放在.init.setup的代码段中,形式为CMD(字符串),命令对应的处理函数:obsolete_checksetup (。进行了所有存放在.init.setup代码段的命令执行针对各种setup段的CMD进行全局变量的赋值。
以上是关于linux内核与文件系统的衔接关系的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核Linux 操作系统结构 ( Linux 内核在操作系统中的层级 | Linux 内核子系统及关系 | 进程调度 | 内存管理 | 虚拟文件系统 | 网络管理 | 进程间通信 )