BusyBox init及其inittab文件分析
2019-07-13 01:57 发布
生成海报
转帖自:http://blog.chinaunix.net/space.php?uid=23089249&do=blog&cuid=2208026
由于BusyBox 自身的一些特点,BusyBox init 非常适合在嵌入式系统开发中使用,被誉为“ 嵌入式linux 的瑞士军刀” ,它可以为嵌入式系统提供只要的init 功能,并且通过定制可以做得非常精炼。inittab 是帮助init 完成系统配置的主要文件。 /* Line is: "id:runlevel_ignored:action:command" */
这是BusyBox-1.11.1 中init.c 文件中的一句注释,该注释指明了inittab 文件中每行的格式。以下对各字段进行简要解析:
1 、id
尽管该格式与发行版linux 的Sys V init 类似,但是,id 在BusyBox 的init 中具有不同的意义。对BusyBox 而言,id 用来指定启动进程的控制终端 。如果所启动的进程并不是可以交互的shell ,例如BusyBox 的sh (ash ),应该会有个控制终端,如果控制终端不存在,BusyBox 的sh 会报错。
2 、runlevel_ignored
由该字段的名称可知,BusyBox init 忽略runlevel_ignored 字段 ,所以配置inittab 时空着它就行了。
4 、command
command 字段用来指定要执行命令(含路径),包括命令行选项。
3 、action
在BusyBox-1.11.1 中init.c 定义了以下8 种action
static const char actions [] = STR_SYSINIT "sysinit/0" STR_RESPAWN "respawn/0" STR_ASKFIRST "askfirst/0" STR_WAIT "wait/0" STR_ONCE "once/0" STR_CTRLALTDEL "ctrlaltdel/0" STR_SHUTDOWN "shutdown/0" STR_RESTART "restart/0" ;
其中,STR_SYSINIT 、STR_RESPAWN 、STR_ASKFIRST 、STR_WAIT 、STR_ONCE 、STR_CTRLALTDEL 、STR_SHUTDOWN 、STR_RESTART 为action_type ,即action 的编码。它们各占1 字节,具体定义如下:
# define STR_SYSINIT "/x01" # define STR_RESPAWN "/x02" # define STR_ASKFIRST "/x04" # define STR_WAIT "/x08" # define STR_ONCE "/x10" # define STR_CTRLALTDEL "/x20" # define STR_SHUTDOWN "/x40" # define STR_RESTART "/x80"
下表列举了这8 种action 的含义 :
action
含义
sysinit
为init 提供初始化命令脚本的路径
respawn
每当相应的进程终止执行时,重新启动该进程
askfirst
类似respawn ,主要用途是减少系统上执行的终端应用程序的数量。它将会促使init 在控制台上显示“Please press Enter to active this console” 的信息,并在重新启动进程之前等待用户按下“enter” 键
wait
告诉init 必须等到相应的进程执行完成之后才能继续执行
once
仅执行相应的进程一次,而且不会等待它执行完成
ctratldel
当按下Ctrl+Alt+Delete 组合键时,执行相应的进程
shutdown
当系统关机时,执行相应的进程
restart
当init 重新启动时,执行相应的进程,通常此处所执行的进程就是init 本身
下面简要介绍一下BusyBox init 怎么对inittab 进行分析执行的。由BusyBox-1.11.1 中init.c 文件可知,BusyBox init 通过init_main 方法对inittab 文件的分析执行,大致过程如下:
1 、init_main 方法先通过parse_inittab 分析inittab 文件,将该文件中的每一行通过new_init_action(uint8_t action_type, const char *command, const char *cons) 添加到init_action_list 列表中。其中cons 就是每行的id 字段。init_action_list 的定义如下:
/* Set up a linked list of init_actions, to be read from inittab */
/* inittab 文件的每一行都会保存为一个 init_action 节点,并且所有 init_action 节点会被链接成一个叫 init_action_list 的列表 */ struct init_action { struct init_action * next ; pid_t pid ; /* 实际执行该 command 的进程 ID*/ uint8_t action_type ; /* action 的类型 */ char terminal [ CONSOLE_NAME_SIZE ]; /* 运行该 command 的终端 */ char command [ COMMAND_SIZE ]; /* 保存 command 字段(含命令行选项) */ }; /* Static variables */ static struct init_action * init_action_list = NULL ;
若不支持ENABLE_FEATURE_USE_INITTAB 或支持ENABLE_FEATURE_USE_INITTAB 但inittab 文件不存在,则执行一个默认的操作,如下:
if ( ENABLE_FEATURE_USE_INITTAB ) file = fopen ( INITTAB , "r" ); else file = NULL ; /* No inittab file -- set up some default behavior */ if ( file == NULL ) { /* 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 QUIT 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 ; }
通过代码中的英文注释,应该都可以看懂该代码。需要解释可能只有INIT_SCRIPT 。INIT_SCRIPT 的定义如下:
#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */
即,BusyBox init 默认的初始化脚本是/etc/init.d/rcS 。
当支持ENABLE_FEATURE_USE_INITTAB 且inittab 文件存在时,BusyBox init 会对inittab 文件进行如下分析:
// 循环获取 inittab 文件中的每一行到
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮