BusyBox init及其inittab文件分析(转)
来源:互联网 发布:手机安装完整版linux 编辑:程序博客网 时间:2024/06/06 17:40
BusyBox init及其inittab文件分析(转)
/* Line is: "id:runlevel_ignored:action:command" */
staticconstchar 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
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 inittab文件分析
- BusyBox init及inittab文件详解
- busybox init inittab passwd
- BUSYBOX init级inittab 文件解释
- busybox init进程分析
- busybox init进程分析
- busybox的init分析
- init进程及inittab文件
- /etc/inittab文件分析
- Busybox init启动过程分析
- busybox的init程序分析
- busybox init启动过程分析
- 详细分析 /etc/inittab 文件
- 嵌入式linux init系统(busybox init)
- AIX中的inittab 文件(转)
- 宏,函数模版方式实现继承方案
- UML关系(泛化,实现,依赖,关联(聚合,组合))
- Linux下软件的安装与卸载(命令行模式)
- LVS开源创始人之淘宝低碳平台构建
- Android Alarm manager 定时闹钟开发详解
- BusyBox init及其inittab文件分析(转)
- cocos2d-x学习笔记-CCAction(动作)
- web标准—可用性、可维护性、可访问性
- 关于使用google map程序中报java.lang.NoClassDefFoundError: android.net.NetworkConnectivityListener的问题
- wsdl中添加soap:header元素
- 关于SSH框架配置文件 Hibernate.cfg.xml 、struts.xml、spring.xml
- 手机扫描条形码二维码原理和实现等网上资料整理
- 我编写的C++程序
- 在Linux中执行.sh脚本,异常/bin/sh^M: bad interpreter: No such file or directory