busybox-
1.18
.
5
分析
文件 init.c
int init_main( int argc UNUSED_PARAM, char **argv)
{
// 填充链表init_action_list
parse_inittab();
原型:new_init_action(uint8_t action_type, const char *command, const char *cons)
{
// 读取文件 /etc/inittab
parser_t *parser = config_open2( " /etc/inittab " , fopen_for_read);
// 假如 /etc/inittab不存在
if (parser == NULL)
{
new_init_action(CTRLALTDEL, " reboot " , "" );
原型 new_init_action(uint8_t action_type, const char *command, const char *cons)
{
struct init_action *a, **nextp;
{
注 : struct init_action {
struct init_action *next; // 链表指针
pid_t pid; // 线程ID
uint8_t action_type; // action的类型 ①
char terminal[CONSOLE_NAME_SIZE]; // 运行该command的终端 (*cons)
char command[COMMAND_SIZE]; // command字段用来指定要执行命令(含路径),包括命令行选项。
};
}
nextp = &init_action_list;
假如init_action_list不为空
{
比较查找
}
假如为空
{
a = xzalloc( sizeof (*a));
}
a->action_type = action_type;
safe_strncpy(a->command, command, sizeof (a->command));
safe_strncpy(a->terminal, cons, sizeof (a->terminal));
}
..........
}
else
{
// 分析
new_init_action( 1 << action, token[ 3 ], tty);
}
}
/* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);
原型: void run_actions( int action_type)
{
struct init_action *a;
for (a = init_action_list; a; a = a->next) {
if (!(a->action_type & action_type))
continue ; // 继续查找
if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) {
pid_t pid = run(a); // 执行
{
创建进程
// ASKFIRST类型需要等待回车
if (BB_MMU && (a->action_type & ASKFIRST)) {
static const char press_enter[] ALIGN1 =
" \nPlease press Enter to activate this console. " ;
char c;
// 输出
dbg_message(L_LOG, " waiting for enter to start '%s' "
" (pid %d, tty '%s')\n " ,a->command, getpid(), a->terminal);
full_write(STDOUT_FILENO, press_enter, sizeof (press_enter) - 1 );
while (safe_read(STDIN_FILENO, &c, 1 ) == 1 && c != ' \n ' )
continue ; // 等待回车
}
}
if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN))
waitfor(pid); // 待它的command执行完,再继续执行。
}
if (a->action_type & (RESPAWN | ASKFIRST)) {
/* Only run stuff with pid == 0. If pid != 0,
* it is already running
*/
if (a->pid == 0 )
a->pid = run(a); // init则不会等待它执行完
}
}
}
check_delayed_sigs();
/* Next run anything that wants to block */
run_actions(WAIT);
check_delayed_sigs();
/* Next run anything to be run only once */
run_actions(ONCE);
while ( 1 ) {
/* (Re)run the respawn/askfirst stuff */
run_actions(RESPAWN | ASKFIRST);
maybe_WNOHANG |= check_delayed_sigs();
/* Don't consume all CPU time - sleep a bit */
sleep( 1 );
maybe_WNOHANG |= check_delayed_sigs();
}
}
① action_type
/* 为init提供初始化命令脚本的路径 */
#define SYSINIT 0x01
/* 告诉init必须等到相应的进程执行完成之后才能继续执行 */
#define WAIT 0x02
/* 仅执行相应的进程一次,而且不会等待它执行完成 */
#define ONCE 0x04
/* 每当相应的进程终止执行时,重新启动该进程 */
#define RESPAWN 0x08
/* 类似respawn,主要用途是减少系统上执行的终端应用程序的数量。
它将会促使init在控制台上显示
“Please press Enter to active this console”的信息,
并在重新启动进程之前等待用户按下“enter”键 */
#define ASKFIRST 0x10
/* 当按下Ctrl+Alt+Delete组合键时,执行相应的进程 */
#define CTRLALTDEL 0x20
/* 当系统关机时,执行相应的进程 */
#define SHUTDOWN 0x40
/* 当init重新启动时,执行相应的进程,通常此处所执行的进程就是init本身 */
文件 init.c
int init_main( int argc UNUSED_PARAM, char **argv)
{
// 填充链表init_action_list
parse_inittab();
原型:new_init_action(uint8_t action_type, const char *command, const char *cons)
{
// 读取文件 /etc/inittab
parser_t *parser = config_open2( " /etc/inittab " , fopen_for_read);
// 假如 /etc/inittab不存在
if (parser == NULL)
{
new_init_action(CTRLALTDEL, " reboot " , "" );
原型 new_init_action(uint8_t action_type, const char *command, const char *cons)
{
struct init_action *a, **nextp;
{
注 : struct init_action {
struct init_action *next; // 链表指针
pid_t pid; // 线程ID
uint8_t action_type; // action的类型 ①
char terminal[CONSOLE_NAME_SIZE]; // 运行该command的终端 (*cons)
char command[COMMAND_SIZE]; // command字段用来指定要执行命令(含路径),包括命令行选项。
};
}
nextp = &init_action_list;
假如init_action_list不为空
{
比较查找
}
假如为空
{
a = xzalloc( sizeof (*a));
}
a->action_type = action_type;
safe_strncpy(a->command, command, sizeof (a->command));
safe_strncpy(a->terminal, cons, sizeof (a->terminal));
}
..........
}
else
{
// 分析
new_init_action( 1 << action, token[ 3 ], tty);
}
}
/* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);
原型: void run_actions( int action_type)
{
struct init_action *a;
for (a = init_action_list; a; a = a->next) {
if (!(a->action_type & action_type))
continue ; // 继续查找
if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) {
pid_t pid = run(a); // 执行
{
创建进程
// ASKFIRST类型需要等待回车
if (BB_MMU && (a->action_type & ASKFIRST)) {
static const char press_enter[] ALIGN1 =
" \nPlease press Enter to activate this console. " ;
char c;
// 输出
dbg_message(L_LOG, " waiting for enter to start '%s' "
" (pid %d, tty '%s')\n " ,a->command, getpid(), a->terminal);
full_write(STDOUT_FILENO, press_enter, sizeof (press_enter) - 1 );
while (safe_read(STDIN_FILENO, &c, 1 ) == 1 && c != ' \n ' )
continue ; // 等待回车
}
}
if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN))
waitfor(pid); // 待它的command执行完,再继续执行。
}
if (a->action_type & (RESPAWN | ASKFIRST)) {
/* Only run stuff with pid == 0. If pid != 0,
* it is already running
*/
if (a->pid == 0 )
a->pid = run(a); // init则不会等待它执行完
}
}
}
check_delayed_sigs();
/* Next run anything that wants to block */
run_actions(WAIT);
check_delayed_sigs();
/* Next run anything to be run only once */
run_actions(ONCE);
while ( 1 ) {
/* (Re)run the respawn/askfirst stuff */
run_actions(RESPAWN | ASKFIRST);
maybe_WNOHANG |= check_delayed_sigs();
/* Don't consume all CPU time - sleep a bit */
sleep( 1 );
maybe_WNOHANG |= check_delayed_sigs();
}
}
① action_type
/* 为init提供初始化命令脚本的路径 */
#define SYSINIT 0x01
/* 告诉init必须等到相应的进程执行完成之后才能继续执行 */
#define WAIT 0x02
/* 仅执行相应的进程一次,而且不会等待它执行完成 */
#define ONCE 0x04
/* 每当相应的进程终止执行时,重新启动该进程 */
#define RESPAWN 0x08
/* 类似respawn,主要用途是减少系统上执行的终端应用程序的数量。
它将会促使init在控制台上显示
“Please press Enter to active this console”的信息,
并在重新启动进程之前等待用户按下“enter”键 */
#define ASKFIRST 0x10
/* 当按下Ctrl+Alt+Delete组合键时,执行相应的进程 */
#define CTRLALTDEL 0x20
/* 当系统关机时,执行相应的进程 */
#define SHUTDOWN 0x40
/* 当init重新启动时,执行相应的进程,通常此处所执行的进程就是init本身 */