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.1init.c文件中的一句注释,该注释指明了inittab文件中每行的格式。以下对各字段进行简要解析: 1id 尽管该格式与发行版linuxSys V init类似,但是,idBusyBoxinit中具有不同的意义。对BusyBox而言,id用来指定启动进程的控制终端。如果所启动的进程并不是可以交互的shell,例如BusyBoxshash),应该会有个控制终端,如果控制终端不存在,BusyBoxsh会报错。 2runlevel_ignored 由该字段的名称可知,BusyBox init忽略runlevel_ignored字段,所以配置inittab时空着它就行了。 4command command字段用来指定要执行命令(含路径),包括命令行选项。 3action  BusyBox-1.11.1init.c定义了以下8action        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_SYSINITSTR_RESPAWNSTR_ASKFIRSTSTR_WAITSTR_ONCESTR_CTRLALTDELSTR_SHUTDOWNSTR_RESTARTaction_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" 下表列举了这8action的含义  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.1init.c文件可知,BusyBox init通过init_main方法对inittab文件的分析执行,大致过程如下:  1init_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_INITTABinittab文件不存在,则执行一个默认的操作,如下:     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_SCRIPTINIT_SCRIPT的定义如下: #define INIT_SCRIPT  "/etc/init.d/rcS" /* Default sysinit script. */ 即,BusyBox init默认的初始化脚本是/etc/init.d/rcS 当支持ENABLE_FEATURE_USE_INITTABinittab文件存在时,BusyBox init会对inittab文件进行如下分析:     //循环获取inittab文件中的每一行到