构建根文件系统之busybox(一)浅析
目录
- busybox(一)浅析
- 引入
- 读取inittab
- 创建执行脚本链表
- 执行脚本
- 小结
busybox(一)浅析
源码包在busybox-1.7.0.tar.bz2
,一个命令对应着一个c
文件,执行init
命令,则是有init.c
,有函数init_main
int init_main(int argc, char **argv);
最终的目的是启动客户的应用程序,需要指定具体的环境
1. 配置文件读取
2. 解析配置文件
3. 执行用户程序
help
相关的帮助可以搜索下/examples
下的文件,比如搜索inittab
,里面有相关说明
#define SYSINIT 0x001 //执行一次等待结束后从链表删除
#define RESPAWN 0x002 //while循环执行
#define ASKFIRST 0x004 //while循环执行,会打印信息,等待回车
#define WAIT 0x008 //执行一次等待结束后从链表删除,在SYSINIT后
#define ONCE 0x010 //与SYSINIT 区别在于不等待其执行结束
#define CTRLALTDEL 0x020 //输入信号后执行
#define SHUTDOWN 0x040 //输入信号后执行
#define RESTART 0x080 //输入信号后执行
流程图
引入
从init_main
函数入口分析,Linux 是按照run_init_process("/sbin/init");
形式调用,没有传递参数,所以执行else
分支,解析配置表
if (argc > 1&& (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1'))
) {/* Start a shell on console */new_init_action(RESPAWN, bb_default_login_shell, "");
} else {/* Not in single user mode -- see what inittab says *//* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,* then parse_inittab() simply adds in some default* actions(i.e., runs INIT_SCRIPT and then starts a pair* of "askfirst" shells */parse_inittab();
}
读取inittab
parse_inittab();
读取inittab
配置表,可以搜索下example
下查看例子帮助,查阅如下格式
Format for each entry: <id>:<runlevels>:<action>:<process>
<id>: WARNING: This field has a non-traditional meaning for BusyBox init!
<runlevels>: The runlevels field is completely ignored.
<action>: Valid actions include: sysinit, respawn, askfirst, wait, once,restart, ctrlaltdel, and shutdown.
<process>: Specifies the process to be executed and it's command line.
标识 | 作用 |
---|---|
id | 自动加上/dev/的前缀,用作终端,stdin,stdout,stderr:printf,scanf,err 可以省略 |
runlevels | 可以忽略 |
action | 指示何止执行 |
process | 应用程序或者可执行脚本 |
最终执行new_init_action
运行脚本程序
默认的配置表读取
#define INITTAB "/etc/inittab" /* inittab file location */
static void parse_inittab(void)
{file = fopen(INITTAB, "r");
}
创建执行脚本链表
for (a = actions; a->name != 0; a++) {if (strcmp(a->name, action) == 0) {if (*id != '\0') {if (strncmp(id, "/dev/", 5) == 0) //这里为id加上/dev/的前缀id += 5;strcpy(tmpConsole, "/dev/");safe_strncpy(tmpConsole + 5, id,sizeof(tmpConsole) - 5);id = tmpConsole;}new_init_action(a->action, command, id);break;}
}
当不存在这个配置表的时候也会有一个默认配置文件,这里以默认的其中一个脚本解析
new_init_action(ASKFIRST, bb_default_login_shell, VC_2);# define VC_2 "/dev/tty2"
#define ASKFIRST 0x004
const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL;
#define LIBBB_DEFAULT_LOGIN_SHELL "-/bin/sh"
也就是最终执行
new_init_action(ASKFIRST, "-/bin/sh", "/dev/tty2");
ASKFIRST 执行的时机
-/bin/sh 脚本程序
/dev/tty2 id终端,加上了/dev/,符合上述描述
分析下new_init_action
函数内部,
- 创建
init_action
结构,包含inittab
中的信息 - 加入到
init_action_list
链表中
for (a = last = init_action_list; a; a = a->next) {/* don't enter action if it's already in the list,* but do overwrite existing actions */if ((strcmp(a->command, command) == 0)&& (strcmp(a->terminal, cons) == 0)) {a->action = action;return;}last = a;
}struct init_action {struct init_action *next;int action; pid_t pid; //对应进程id, process idchar command[INIT_BUFFS_SIZE]; //对应应用程序 char terminal[CONSOLE_NAME_SIZE]; //对应终端
};
由此,可以理解当配置文件不存在的时候,会去创建配置表
#define INITTAB "/etc/inittab" /* inittab file location */file = fopen(INITTAB, "r");if (file == NULL) {/* No inittab file -- set up some default behavior *//* Reboot on Ctrl-Alt-Del */new_init_action(CTRLALTDEL, "reboot", "");/* Umount all filesystems on halt/reboot */new_init_action(SHUTDOWN, "umount -a -r", "");/* Swapoff on halt/reboot */if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");/* Prepare to restart init when a HUP is received */new_init_action(RESTART, "init", "");/* Askfirst shell on tty1-4 */new_init_action(ASKFIRST, bb_default_login_shell, "");new_init_action(ASKFIRST, bb_default_login_shell, VC_2);new_init_action(ASKFIRST, bb_default_login_shell, VC_3);new_init_action(ASKFIRST, bb_default_login_shell, VC_4);/* sysinit */new_init_action(SYSINIT, INIT_SCRIPT, "");return;}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>↓
创建类似的inittatb ↓
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>↓
::CTRLALTDEL:reboot
::SHUTDOWN:umount -a -r
::RESTART:init
::ASKFIRST:-/bin/sh:
tty2::ASKFIRST:-/bin/sh
tty3::ASKFIRST:-/bin/sh
tty4::ASKFIRST:-/bin/sh
::SYSINIT:/etc/init.d/rcS
执行脚本
脚本有多种类型,不同类型执行方式与时机不同
#define SYSINIT 0x001 //执行一次等待结束后从链表删除
#define RESPAWN 0x002 //while循环执行
#define ASKFIRST 0x004 //while循环执行,会打印信息,等待回车
#define WAIT 0x008 //执行一次等待结束后从链表删除,在SYSINIT后
#define ONCE 0x010 //与SYSINIT 区别在于不等待其执行结束
#define CTRLALTDEL 0x020 //输入信号后执行
#define SHUTDOWN 0x040 //输入信号后执行
#define RESTART 0x080 //输入信号后执行
run_actions(SYSINIT);waitfor(a, 0);//执行a,等待执行结束run(a);//执行创建process子进程waitpid(runpid, &status, 0);delete_init_action(a);//删除链表/* Next run anything that wants to block */run_actions(WAIT);waitfor(a, 0);//执行a,等待执行结束run(a);//执行创建process子进程waitpid(runpid, &status, 0);delete_init_action(a);//删除链表/* Next run anything to be run only once */run_actions(ONCE);run(a);delete_init_action(a);/* Now run the looping stuff for the rest of forever */while (1) {//重新运行pid已经退出的子进程run_actions(RESPAWN);if (a->pid == 0) { //默认pid为0a->pid = run(a);}run_actions(ASKFIRST);if (a->pid == 0) {a->pid = run(a);}//打印"\nPlease press Enter to activate this console. ";,//等待输入回车//创建子进程wpid = wait(NULL);//等待子进程退出while (wpid > 0) {a->pid--;//推出后pid=0}}}
小结
- 打开终端
dev/console
- 打开
dev/null
,用作不设置终端id
的时候的定位 - 读取配置文件
etc/inittab
,需要存在配置文件的可执行程序或者脚本 - 执行脚本
所以一个最小的根文件系统必备的一些资源
dev/console
dev/null
sbin/init-------------busybox提供,至少需要这个应用程序,这是linux启动的第一个应用程序
etc/inittab-----------配置文件,定义了一些应用程序
配置文件制定的应用程序----配置文件指定的应用程序
C库--------------------应用程序的C库
构建根文件系统之busybox(一)浅析相关推荐
- 构建根文件系统之busybox(三)最小根文件系统
目录 busybox(三)最小根文件系统 引入 构建终端 构造inittab 配置应用程序 构建C库 制作映像文件yaffs busybox(三)最小根文件系统 引入 在busybox(一)浅析中,得 ...
- 构建根文件系统之busybox(四)完善
目录 busybox(四)完善 proc挂载 手动挂载 proc解析 使用脚本自动挂载 使用mount-a挂载 udev/mdev 挂载 使用jffs2 文件系统格式 安装zlib 安装jffs2 生 ...
- 构建根文件系统(2)Busybox init 进程
讲init进程的启动过程从/etc/inittab出发. 内核启动init进程时已经打开/dev/console设备作为控制台,一般情况下Busybox init程序就使用/dev/console, ...
- 构建根文件系统之busybox(二)编译
目录 busybox(二)编译 busybox(二)编译 1.解压,源码包在busybox-1.7.0.tar.bz2, tar xjf busybox-1.7.0.tar.bz2 cd busybo ...
- 韦东山衔接班——4.3_构建根文件系统之busybox
作者:GWD 时间:2019.8.26 注:Linux中交叉编译用CROSS开头 配置编译busybox 1.解压busybox 2.make menuconfig出现配置菜单 在readme或者in ...
- 2.3【Linux系统移植之三】:使用BusyBox构建根文件系统(rootfs)
文章目录 一.搭建NFS服务器 二.使用BusyBox构建跟文件系统 2.1 修改顶层Makefile 2.2 busybox中文支持 2.3 配置busybox 2.4 编译busybox 2.5 ...
- 【ARM】使用Busybox构建根文件系统
Busybox构建根文件系统 介绍 下载 配置busybox 配置交叉编译器 取消静态库编译 添加vi命令的支持 取消简化模块 支持mdev 中文支持 编译 完善根文件系统 创建必要文件夹 复制库 启 ...
- 教你用 buildroot 构建根文件系统
如果想要构建完整的根文件系统,大家一般都是使用buildroot,它不仅包含了 busybox 的功能,而且里面还集成了各种软件,需要什么软件就选择什么软件,不需要我们去移植. 嵌入式系统三大部分:b ...
- 构建根文件系统(一)
接着前边内核移植的文章,记录根文件系统的构建. 这里要用到强大的busybox,我选择的版本是busybox-1.18.5.tar.bz2 ,1.17的也可以:之所以选择这个版本是因为基于现在的交叉编 ...
最新文章
- MM--发票校验 及基于采购订单的MIRO发票校验过程
- linux光盘补救,Linux_忘记root密码时使用Linux系统光盘进行补救的方法,救援模式即rescue ,这个模式主 - phpStudy...
- .NET技术之美-网络编程
- python作业:高级FTP程序
- Angular常用命令行和指令
- 成员变量(全局变量)和局部变量区别
- 外卖和快递行业数据_外卖和快递骑手管理“上轨道”
- 14个非常棒的 JavaScript 游戏开发框架推荐
- vsftpd配置好防火墙后从网页登录ftp却无法访问此页面
- 兄弟们,请求支援,怎么实现互通,全部都互通的
- StringBuffer 的 各种方法
- mysql提高count_mysql count提高方法总结
- javascript中Object类原型对象的属性和方法
- easyui 提示框组件_jQuery EasyUI 教程-Tooltip(提示框)
- 构造c语言的上下文无关文法,正则文法和上下文无关文法
- C++多线程并发(五)---原子操作与无锁编程
- python requests 代理ip被禁_python requests 测试代理ip是否生效
- 中山c 语言培训中心,中山英语口语培训中心
- [扩欧]JZOJ 5855 吃蛋糕
- 机械键盘改罗技优联无线键盘