BUSYBOX init级inittab 文件解释
来源:互联网 发布:网络基础与组网技术 编辑:程序博客网 时间:2024/06/06 11:01
BusyBox init及其inittab文件分析(转)
2010-09-17 11:14:05| 分类:linux applicatio | 标签:|字号大中小 订阅
由于BusyBox自身的一些特点,BusyBox init非常适合在嵌入式系统开发中使用,被誉为“嵌入式linux的瑞士军刀”,它可以为嵌入式系统提供只要的init功能,并且通过定制可以做得非常 精炼。inittab是帮助init完成系统配置的主要文件。
/* Line is: "id:runlevel_ignored:action:command" */
staticconst 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"
;
#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"
/* 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;
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;
}
//循环获取inittab文件中的每一行到buf中
while(fgets(buf, COMMAND_SIZE,file) != NULL){
//定义action的种类
static constchar 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"
;
char tmpConsole[CONSOLE_NAME_SIZE];
char *id,*runlev, *action, *command;
const char*a;
/*通过跳过空格,并截取到换行\n为止,来获取本行的有效内容,并保存于id中*/
/* Skip leading spaces */
id = skip_whitespace(buf);
/* Trim the trailing '\n' */
*strchrnul(id,'\n') = '\0';
//若为注释,跳出本次循环
/* Skip the line if it is a comment */
if (*id== '#' || *id == '\0')
continue;
/* Line is: "id:runlevel_ignored:action:command" */
//获取runlev字段
runlev =strchr(id,':');
if (runlev== NULL /*|| runlev[1] == '\0' - not needed */)
goto bad_entry;
//获取action字段
action =strchr(runlev + 1, ':');
if (action== NULL /*|| action[1] == '\0' - not needed */)
goto bad_entry;
//获取command字段
command =strchr(action + 1, ':');
if (command== NULL || command[1]== '\0')
goto bad_entry;
/*循环遍历actions数组,查找数组中与action字段相同的元素。找到后,通过new_init_action方法,将该元素的第一个字符(即action_type编码)和id及command字段作为一init_action节点添加到init_action_list列表中。接着跳到下一行进行处理*/
*command= '\0';/* action => ":action\0" now */
for (a = actions; a[0]; a+= strlen(a)+ 1) {
//查到数组actions中与action字段相同的元素
if(strcmp(a+ 1, action + 1) == 0){
//截取id字段,格式为"id\0"
*runlev= '\0';
//若id字段非空
if(*id != '\0'){
//若id字段带前缀/dev/,先截掉该前缀
if(strncmp(id,"/dev/", 5)== 0)
id += 5;
//复制字符串/dev/到tmpConsole临时缓存区中
strcpy(tmpConsole,"/dev/");
/*再将id字段复制到tmpConsole第5个字符之后,即/dev/之后。这样tmpConsole就成为了某一设备文件名(含路径)。对于BusyBox init来说,tmpConsole是终端设备*/
safe_strncpy(tmpConsole+ 5, id,
sizeof(tmpConsole)- 5);
/*来到这里,应该就明白为什么BusyBox init的id字段是控制终端*/
id = tmpConsole;
}
//将action_type、command和控制终端id作为一init_action节点,添加到init_action_list列表中。从这里可以看出BusyBox init忽略了runlevel字段
new_init_action((uint8_t)a[0], command + 1, id);
goto next_line;
}
}
*command =':';
/* Choke on an unknown action */
bad_entry:
message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", id);
next_line: ;
}
/* Run all commands of a particular type */
static void run_actions(int action_type)
{
struct init_action *a, *tmp; // 遍历init_action_list列表,查找类型为action_type的节点
for (a = init_action_list; a; a= tmp) {
tmp = a->next;
//查到类型为action_type的节点
if (a->action_type& action_type) {
// Pointless: run() will error out if open of device fails.
///* a->terminal of "" means "init's console" */
//if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
// //message(L_LOG | L_CONSOLE, "Device %s cannot be opened in RW mode", a->terminal /*, strerror(errno)*/);
// delete_init_action(a);
//} else
if (a->action_type& (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN| RESTART)){/*若该节点类型为SYSINIT、WAIT、CTRLALTDEL、SHUTDOWN和RESTART的init_action,init会等待它的command执行完,再继续执行。并且command执行完后,删除该节点*/
waitfor(run(a));
delete_init_action(a);
} elseif (a->action_type& ONCE) {
/*action_type为ONCE的init_action,init则不会等待它执行完,并且将该节点从init_action_list中删除*/
run(a);
delete_init_action(a);
} elseif (a->action_type& (RESPAWN | ASKFIRST)){
/* Only run stuff with pid==0. If they have
* a pid, that means it is still running */
/*当action_type为RESOAWN或ASKFIRST的init_action,且执行该init_action的command的进程已死 (通过a->pid == 0判断,已死RESOAWN或ASKFIRST的command进程,其init_action的pid域都会在init_main方法被置为0,具体见 本文最后一段源码)时,调用run方法fork一子进程(用于执行command),并将run返回的子进程ID保存于init_action的pid 域*/
if (a->pid== 0){
a->pid= run(a);
}
}
}
}
}
/* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);
/* Next run anything that wants to block */
run_actions(WAIT);
/* Next run anything to be run only once */
run_actions(ONCE);
/* Now run the looping stuff for the rest of forever */
while (1){
/* run the respawn/askfirst stuff */
run_actions(RESPAWN | ASKFIRST);
/* Don't consume all CPU time -- sleep a bit */
sleep(1);
/* Wait for any child process to exit */
wpid = wait(NULL);
while (wpid> 0) {
/* Find out who died and clean up their corpse */
for (a= init_action_list; a; a= a->next){
if (a->pid== wpid){
/* Set the pid to 0 so that the process gets
* restarted by run_actions() */
a->pid= 0;
message(L_LOG,"process '%s' (pid %d) exited. "
"Scheduling for restart.",
a->command, wpid);
}
}
/* see if anyone else is waiting to be reaped */
wpid = wait_any_nohang(NULL);
}
}
}
- BUSYBOX init级inittab 文件解释
- BusyBox init及其inittab文件分析
- BusyBox init及其inittab文件分析
- BusyBox init及inittab文件详解
- busybox init inittab passwd
- BusyBox init及其inittab文件分析(转)
- busybox inittab文件分析
- INITTAB 文件解释
- init进程及inittab文件
- 【Busybox】inittab详解
- 【Busybox】inittab详解
- init和/etc/inittab
- linux /etc/inittab文件的字段解释及其说明
- inittab文件
- inittab文件
- inittab文件
- inittab文件
- 【Busybox】Busybox init启动过程
- Ajax 在IE浏览器中的缓存问题
- git常用命令(对付差记性,不断更新的笔记)
- 使用busybox定制自己的应用程序
- Delphi图像处理
- Linux下静态库编译
- BUSYBOX init级inittab 文件解释
- CTimeSpan得到日期差
- 解析 HTML DocumentType 元素
- 句柄
- win7共享WiFi
- 门户站基础css样式命名、应用原则和部分门户站的全局CSS
- Oracle小知识总结
- Flash 命令大全
- spring动态加载hibernate