farsight 构建Linux根文件系统
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
构建Linux根文件系统
1. 根文件系统
1.1 定义
存放系统启动所必需的文件
内核映像文件(嵌入式系统中,内核一般单独存放在一个分区中);
内核启动后运行的第一个程序(init);
shell程序;
应用程序所依赖的库;
…...
1.2 目录结构
1.2.1 FHS标准:
(Filesystem Hierarchy Standard,文件系统层次标准);
定义文件系统中目录、文件存放的原则,不是强制性标准。
1.2.2 目录:
/bin
存放所有用户都可以使用的、基本的命令;
比须和根文件系统在一个分区中。
/sbin
存放系统命令,只有管理员可以使用的命令
必须和根文件系统在同一分区中。
/---/sbin
*基本的系统命令,用于启动系统、修复系统等。
*---/usr/sbin
*不是急迫需要使用的系统命令。
*---/usr/local/sbin
/本地安装的系统命令。
/dev:存放设备文件。
/etc:存放配置文件。
/lib
/---libc.so.*动态链接C库。
*---ld*链接器、加载器。
/---modules内核可加载模块存放的目录。
/home:用户目录。
/root:根用户目录。
/usr
存放共享、只读的数据和程序;
可以存放在另一个分区中,系统启动后再挂接到根文件系统的/usr目录下。
/var:存放可变的数据。
/proc
proc文件系统的挂接点;
proc文件系统是一个虚拟的文件系统,用来表示系统的运行状态。
/mnt:用于临时挂接某个文件系统的挂接点。
/tmp
用于存放临时文件;
为减少对Flash的操作,可以在/tmp目录上挂接内存文件系统。
2. Busybox
2.1 init进程
2.1.1 定义
由内核启动的第一个(唯一的一个)用户进程(ID=1);
是后续所有进程的发起者,根据配置文件决定启动哪些程序;
执行的程序通常是/sbin/init,也可以传入命令行参数指定一个程序作为init进程运行。
2.1.2 内核如何启动init进程
内核启动的最后一步是启动init进程,代码在linux内核源码的init/main.c中。static int noinline init_post(void)
{
free_initmem();
unlock_kernel();
mark_rodata_ro();
system_state = SYSTEM_RUNNING;
numa_default_policy();
/*打开标准输入(stdin)、标准输出(stdout)、标准错误(stderr);
*对应的文件描述符分别是0,1,2。
*/
//打开/dev/console设备文件,他是init进程的标准输入设备。
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) printk(KERN_WARNING "Warning: unable to open an initial console.\n");
//将文件描述符0复制给文件描述符1,2;
//标准输入、标准输出、标准错误对应同一个文件(设备)。
(void) sys_dup(0);
(void) sys_dup(0);
/*ramdisk_execute_command
*指定了要执行的程序
*1. ”
如果命令行参数中指定了rdinit=...”
*ramdisk_execute_command等于此指定值。
*2. 如果/init程序存在
*ramdisk_execute_command=/init
*3. ramdisk_execute_command为空。
*/
if (ramdisk_execute_command) {
/*run_init_process函数
*使用他的参数所指定的程序来创建一个用户进程;
*一旦创建进程成功,此函数将不会返回。
*/
run_init_process(ramdisk_execute_command);
printk(KERN_WARNING "Failed to execute %s\n",
ramdisk_execute_command);
}
/*execute_command
*指定了要执行的程序
*1. ”
如果命令行参数中指定了init=...”
* execute_command等于此指定值。
*2. execute_command为空
*/
if (execute_command) {
run_init_process(execute_command);
printk(KERN_WARNING "Failed to execute %s. Attempting "
"defaults...\n", execute_command);
}
//依次尝试执行/sbin/init、/etc/init、/bin/init、/bin/sh。
run_init_process("/sbin/init");
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.");
}
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
static void run_init_process(char *init_filename)
{
argv_init[0] = init_filename;
kernel_execve(init_filename, argv_init, envp_init);
}
2.1.3 Busybox init程序流程
设置信号处理函数;
初始化控制台;
解析inittab。
2.1.4 初始化控制台
进程时打开了/dev/console”设备作为控制台,一般情况下Busybox init程内核启动init”
序使用/dev/console;
如果内核启动init进程时设置了环境变量CONSOLE或是console,则使用环境变量所指定
程序中,会检查这个设备是否可以打开,如果不能打开则使用/dev/null”。的设备。Busybox init”
2.1.5 解析/etc/inittab文件
/etc/inittab文件中的每个条目用来定义一个子进程,并确定他的启动方法。
格式:
如果程序是交互的,字段前加上-”字符。
”
/*sysinit
*系统启动后最先执行,只执行一次;
*init进程等他结束后继续执行其他动作。
*wait
*系统执行完sysinit后,只执行一次;
*init进程等他结束后继续执行其他动作。
*once
*系统执行完wait进程后,只执行一次;