制作根文件系统之Busybox init进程的启动过程分析
先来介绍一下什么是Busybox:它是将众多的UNIX命令集合进一个很小的可执行程序中。
在制作根文件系统之内核如何启动init进程中遗留了一个问题是/linuxrc是内核启动的第一个应用程序,那么它是什么?我们看到移植好的根文件系统环境,输入ls -al /linuxrc。可以看到:
lrwxrwxrwx Jul linuxrc -> bin/busybox
/linuxrc其实是指向Busybox的,它其实是Busybox下的一个程序,所以我们需要分析Busybox的源码来研究/linuxrc这个程序做的事情,当在移植好的根文件系统环境下输入/linuxrc可以看到:
# busybox linuxrc
init started: BusyBox v1.7.0 (-- :: CST)
starting pid , tty '': '/etc/init.d/rcS' Please press Enter to activate this console.
这就是执行linuxrc程序之后出现的界面,现在还不确定/linuxrc是Busybox下哪个文件,我们搜索“init started”,在busybox-1.7.0\init\Init.c中找到了它
message(MAYBE_CONSOLE | L_LOG, "init started: %s", bb_banner);
我们看到调用它的是init_main函数,接下去就是分析这个函数,init_main函数的功能大概可以概括为
1、设置处理信号函数
2、读取配置文件、解析配置文件
3、根据配置文件执行用户的程序或脚本
下面分别介绍
1、设置处理信号函数,restart, ctrlaltdel, and shutdown是一些按键事件,这些处理函数在接收到按下相关按键的信号后,进行处理
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);
2、读取和解析配置文件,先看一下配置文件的格式,文档位于example/inittab中
# inittab的格式为:
# <id>:<runlevels>:<action>:<process>
# id => /dev/id,用作终端:stdin、stdout、stderr:printf、scanf、err
# runlevels:忽略
# action :执行时机Valid actions include: sysinit, respawn, askfirst, wait, once,
restart, ctrlaltdel, and shutdown.
# process :应用程序或脚本
接着回到init_main函数,看到
parse_inittab();//解析inittab参数
找到parse_inittab函数,位于busybox-1.7.0\init\Init.c中
static void parse_inittab(void)
{
...
...
file = fopen(INITTAB, "r");//以只读方式打开/etc/inittab
...
while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
...
for (a = actions; a->name != ; a++) {
if (strcmp(a->name, action) == ) {
if (*id != '\0') {
if (strncmp(id, "/dev/", ) == )//去掉开头的/dev/
id += ;
strcpy(tmpConsole, "/dev/");
safe_strncpy(tmpConsole + , id,
sizeof(tmpConsole) - );
id = tmpConsole;
}
new_init_action(a->action, command, id);//创建一个init_action结构,以解析出来的参数填充它,然后将这个结构放入init_action_list链表
break;
}
}
...
}
}
这个函数的功能解释为打开/etc/inittab文件然后处理它,这个文件是以配置文件的格式存放的。看到函数最后会创建一个init_action结构,这个结构就是将配置文件里的内容一个个取出来,然后放在里面。最后链接到init_action_list链表中
struct init_action {
struct init_action *next;
int action;
pid_t pid;//进程号 by andy
char command[INIT_BUFFS_SIZE];//要执行的脚本命令
char terminal[CONSOLE_NAME_SIZE];//终端
};
这里再举个例子,下面是某个配置文件。以第一个为例子。action为askfirst执行时机;command为执行的命令或脚本为-/bin/sh;terminal为使用的中断为console
console::askfirst:-/bin/sh
::sysinit:/etc/init.d/rcS
3、根据配置文件执行用户的程序或脚本
接着看到,每个执行时机执行的内容,以下均为简写。
busybox-> init_main
parse_inittab
file = fopen(INITTAB, "r");//打开配置文件/etc/inittab
new_init_action //a、创建一个init_action结构,填充
//b、将这个结构放入init_action_list链表
run_actions(SYSINIT);
waitfor(a, ); //执行应用程序,等待它执行完毕
run(a) //创建process子进程
waitpid(runpid, &status, );//等待它结束
delete_init_action(a);//在init_action_list链表里删除
run_actions(WAIT);
waitfor(a, ); //执行应用程序,等待它执行完毕
run(a) //创建process子进程
waitpid(runpid, &status, );//等待它结束
delete_init_action(a);//在init_action_list链表里删除
run_actions(ONCE);
run(a); //创建process子进程
delete_init_action(a);//在init_action_list链表里删除
while() {
run_actions(RESPAWN);
if (a->pid == ) {
a->pid = run(a);
}
run_actions(ASKFIRST);
if (a->pid == ) {
a->pid = run(a);
打印:Please press Enter to activate this console.
等待回车
创建子进程
}
wpid = wait(NULL);//等待子进程退出
while (wpid > ) {
a->pid = ;//退出后就设置pid=0
}
其余三个restart, ctrlaltdel, and shutdown执行时机在按下按键的时候发生事件
}
大致总结一下每个执行时机:
SYSINIT:第一个执行,创建子进程,等待进程结束,将它从init_action_list链表里删除
WAIT:第二个执行,创建子进程,等待进程结束,将它从init_action_list链表里删除
ONCE:第三个执行,创建子进程,将它从init_action_list链表里删除
RESPAWN:循环执行
ASKFIRST:循环执行,打印:Please press Enter to activate this console,等待回车后,创建子程序-/bin/sh,就不再返回了
restart, ctrlaltdel, and shutdown:在按键按下的时候随时执行
这样就分析完了Busybox的init程序,ASKFIRST时机相关的脚本或命令执行以后,因为脚本有-/bin/sh,所以最终会进入sh进程。它位于shell\Ash.c下的ash_main函数,这个函数就不分析了。到这里从uboot开始一直到根文件系统下的第一个用户程序全部分析完成。
制作根文件系统之Busybox init进程的启动过程分析的更多相关文章
- 第4阶段——制作根文件系统之分析init进程(2)
本节目标: (1) 了解busybox(init进程和命令都放在busybox中) (2) 创建SI工程,分析busybox源码来知道init进程做了哪些事情 (3) 分析busybox中init进 ...
- 制作根文件系统之内核如何启动init进程
start_kernel其实也是内核的一个进程,它占用了进程号0,start_kernel的内容简写如下: asmlinkage void __init start_kernel(void) //内核 ...
- 利用busybox制作根文件系统
实际项目中可以使用Buildroot制作根文件系统 1.busybox源码下载及配置 https://busybox.net/downloads/ 1.1.修改Makefile (1) ARCH = ...
- 使用BusyBox制作根文件系统【转】
本文转载自:http://www.cnblogs.com/lidabo/p/5300180.html 1.BusyBox简介 BusyBox 是很多标准 Linux 工具的一个单个可执行实现.Busy ...
- 使用BusyBox制作根文件系统
1.BusyBox简介 BusyBox 是很多标准 Linux 工具的一个单个可执行实现.BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大.更复杂的工具,例如 gre ...
- 通过busybox制作根文件系统
通过busybox制作根文件系统可以自定义选项,在制作的根文件系统中添加需要的命令,指定生成的根文件系统到相应的目录下. 一. 根文件系统的获取方式--->官网: https://busybox ...
- 通过busybox制作根文件系统详细过程
我在之前的uboot通过NFS挂载ubuntu根文件系统中也有实现过根文件系统的制作,那只是在ubuntu官网已经做好的根文件基础上安装一些自己所需的软解而已.而使用busybox制作根文件系统可以自 ...
- 使用Busybox-1.2.0制作根文件系统
使用Busybox-1.2.0制作根文件系统 cross-3.3.2 make-3.8.1 STEP 1: 创建根文件系统目录,主要包括以下目录/bin,/etc,/dev,/mnt,/sbin,/u ...
- 根文件系统及Busybox简介
转:http://blog.csdn.net/wqc02/article/details/8930184 1.根文件系统简介...2 2.Busybox简介...2 2.1Busybox简介...2 ...
随机推荐
- [PHP]对Json字符串解码返回NULL的一般解决方案
---------------------------------------------------------------------------------------------------- ...
- Structs复习 Action
引入jar包 web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version= ...
- oracle合并语句
在sql server中的合并语句可以用xml path 详见http://www.cnblogs.com/codeyu/archive/2010/05/25/1743474.html 而oracle ...
- 一: Introduction(介绍)
Welcome to SQLBackupRestore.com, your online resource for SQL Server backup and recovery issues. Th ...
- 吴裕雄 python 机器学习-KNN算法(1)
import numpy as np import operator as op from os import listdir def classify0(inX, dataSet, labels, ...
- 函数练习以及 if else 三元运算
- idea 这样 会快点
最近使用IDEA来开发JAVA应用,对IDEA的界面很有爱,但是缺受不了它的运行速度.每次运行都要编译,所以就有了这边文章 总感觉IDEA的编译速度比eclipse慢,eclipse每次保存都自动 ...
- numpy 矩阵变换 reshape ravel flatten
1. 两者的区别在于返回拷贝(copy)还是返回视图(view),numpy.flatten()返回一份拷贝,对拷贝所做的修改不会影响(reflects)原始矩阵,而numpy.ravel()返回的是 ...
- kafka消息队列的简单理解
kafka在大数据.分布式架构中都很流行.kafka可以进行流式计算,也可以做为日志系统,还可以用于消息队列. 本篇主要是消息队列相关的知识. 零.kafka作为消息队列的优点: 分布式的系统 高吞吐 ...
- AI图谱