制作根文件系统之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 查看当前页中的post及get数据
file_put_contents("log1209.html",date('Y-m-d H:i:s ')."-----<br>",FILE_APP ...
- 第六次Scrum冲刺
第六次Scrum冲刺 1.成员今日完成情况 队员 今日完成任务 刘佳 前端构建 李佳 后端设计 周世元 数据设计 杨小妮 博客编写 许燕婷 管理团队当日及次日任务 陈水莲 性能测试用例设计 曾丽丽 性 ...
- Hibernate 再接触 关系映射 一对一单向外键联合主键关联
例子: Husband.java package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persiste ...
- spring boot 使用war包部署
- 吴裕雄 15-MySQL LIKE 子句
我们知道在 MySQL 中使用 SQL SELECT 命令来读取数据, 同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录.WHERE 子句中可以使用等号 = 来设定获取数据的 ...
- 吴裕雄 python神经网络(7)
import numpy as npnp.random.randint(0,49,3) # -*- coding:utf-8 -*-import kerasfrom keras.models impo ...
- Vue 中select option默认选中的处理方法
在做泰康项目的时候有个需求就是要给select默认选中的样式我的处理方法有两个 1.直接将默认值给 selectedOption <select v-model="selectedO ...
- phpexcel 导入超过26列时的解决方案
$highestColumn = $sheet->getHighestColumn(); // 取得总列数 ++$highestColumn; for ($row = 5; $row <= ...
- el-js中循环遍历el的集合
遇到问题的代码: var score=0; for(var i=0;i<${fn:length(tMovie.tComments) };i++){ score=${tMovie.tComment ...
- 用jQuery实现轮播图效果,js中的排他思想
---恢复内容开始--- jQuery实现轮播图不用单独加载. 思路: a. 通过$("#id名");选择需要的一类标签,获得一个伪数组 b.由于是伪数组的原因,而对数组的处理最多 ...