init/init.c
int init_main(int argc UNUSED_PARAM, char **argv)
{
struct sigaction sa;
INIT_G();
/* Some users send poweroff signals to init VERY early.
* To handle this, mask signals early.
*/
/* sigemptyset(&G.delayed_sigset); - done by INIT_G() */
sigaddset(&G.delayed_sigset, SIGINT); /* Ctrl-Alt-Del */
sigaddset(&G.delayed_sigset, SIGQUIT); /* re-exec another init */
#ifdef SIGPWR
sigaddset(&G.delayed_sigset, SIGPWR); /* halt */
#endif
sigaddset(&G.delayed_sigset, SIGUSR1); /* halt */
sigaddset(&G.delayed_sigset, SIGTERM); /* reboot */
sigaddset(&G.delayed_sigset, SIGUSR2); /* poweroff */
#if ENABLE_FEATURE_USE_INITTAB
sigaddset(&G.delayed_sigset, SIGHUP); /* reread /etc/inittab */
#endif
sigaddset(&G.delayed_sigset, SIGCHLD); /* make sigtimedwait() exit on SIGCHLD */
sigprocmask(SIG_BLOCK, &G.delayed_sigset, NULL);
#if DEBUG_SEGV_HANDLER
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = handle_sigsegv;
sa.sa_flags = SA_SIGINFO;
sigaction_set(SIGSEGV, &sa);
sigaction_set(SIGILL, &sa);
sigaction_set(SIGFPE, &sa);
sigaction_set(SIGBUS, &sa);
#endif
if (argv[1] && strcmp(argv[1], "-q") == 0) {
return kill(1, SIGHUP);
}
#if !DEBUG_INIT
/* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
if (getpid() != 1
&& (!ENABLE_LINUXRC || applet_name[0] != 'l') /* not linuxrc? */
) {
bb_simple_error_msg_and_die("must be run as PID 1");
}
# ifdef RB_DISABLE_CAD
/* Turn off rebooting via CTL-ALT-DEL - we get a
* SIGINT on CAD so we can shut things down gracefully... */
reboot(RB_DISABLE_CAD); /* misnomer */
# endif
#endif
/* If, say, xmalloc would ever die, we don't want to oops kernel
* by exiting.
* NB: we set die_func *after* PID 1 check and bb_show_usage.
* Otherwise, for example, "init u" ("please rexec yourself"
* command for sysvinit) will show help text (which isn't too bad),
* *and sleep forever* (which is bad!)
*/
die_func = sleep_much;
/* Figure out where the default console should be */
console_init();
set_sane_term();
xchdir("/");
setsid();
/* Make sure environs is set to something sane */
putenv((char *) "HOME=/");
putenv((char *) bb_PATH_root_path);
putenv((char *) "SHELL=/bin/sh");
putenv((char *) "USER=root"); /* needed? why? */
if (argv[1])
xsetenv("RUNLEVEL", argv[1]);
#if !ENABLE_FEATURE_INIT_QUIET
/* Hello world */
message(L_CONSOLE | L_LOG, "init started: %s", bb_banner);
#endif
/* Check if we are supposed to be in single user mode */
if (argv[1]
&& (strcmp(argv[1], "single") == 0 || strcmp(argv[1], "-s") == 0 || LONE_CHAR(argv[1], '1'))
) {
/* ??? shouldn't we set RUNLEVEL="b" here? */
/* Start a shell on console */
new_init_action(RESPAWN, bb_default_login_shell, "");
} else {
/* Not in single user mode - see what inittab says */
/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
* then parse_inittab() simply adds in some default
* actions (i.e., INIT_SCRIPT and a pair
* of "askfirst" shells) */
parse_inittab(); // 一上来 就解析和读取inittab文件
}
#if ENABLE_SELINUX
if (getenv("SELINUX_INIT") == NULL) {
int enforce = 0;
putenv((char*)"SELINUX_INIT=YES");
if (selinux_init_load_policy(&enforce) == 0) {
BB_EXECVP(argv[0], argv);
} else if (enforce > 0) {
/* SELinux in enforcing mode but load_policy failed */
message(L_CONSOLE, "can't load SELinux Policy. "
"Machine is in enforcing mode. Halting now.");
return EXIT_FAILURE;
}
}
#endif
#if ENABLE_FEATURE_INIT_MODIFY_CMDLINE
/* Make the command line just say "init" - that's all, nothing else */
strncpy(argv[0], "init", strlen(argv[0]));
/* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
while (*++argv)
nuke_str(*argv);
#endif
/* Set up STOP signal handlers */
/* Stop handler must allow only SIGCONT inside itself */
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sigdelset(&sa.sa_mask, SIGCONT);
sa.sa_handler = stop_handler;
sa.sa_flags = SA_RESTART;
sigaction_set(SIGTSTP, &sa); /* pause */
/* Does not work as intended, at least in 2.6.20.
* SIGSTOP is simply ignored by init
* (NB: behavior might differ under strace):
*/
sigaction_set(SIGSTOP, &sa); /* pause */
/* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);
check_delayed_sigs(&G.zero_ts);
/* Next run anything that wants to block */
run_actions(WAIT);
check_delayed_sigs(&G.zero_ts);
/* Next run anything to be run only once */
run_actions(ONCE);
/* Now run the looping stuff for the rest of forever */
while (1) {
/* (Re)run the respawn/askfirst stuff */
run_actions(RESPAWN | ASKFIRST);
/* Wait for any signal (typically it's SIGCHLD) */
check_delayed_sigs(NULL); /* NULL timespec makes it wait */
/* Wait for any child process(es) to exit */
while (1) {
pid_t wpid;
struct init_action *a;
wpid = waitpid(-1, NULL, WNOHANG);
if (wpid <= 0)
break;
a = mark_terminated(wpid);
if (a) {
message(L_LOG, "process '%s' (pid %u) exited. "
"Scheduling for restart.",
a->command, (unsigned)wpid);
}
}
/* Don't consume all CPU time - sleep a bit */
sleep1();
} /* while (1) */
}
(1)读取和解析/etc/inittab,根据inittab里面的设置,启动不同的进程
(2)运行inittab系统初始化rcs脚本
::sysinit:/etc/init.d/rcS
mount -a 根据/etc/fstab 挂载相应的系统
可配置ip地址
ifconfig eth0 xxxx netmask 255.255.255.0
route add default gw xxx
route add xx dev eth0
mount -o nolock xxx:xxx /mnt
mount -o nolock xxxx:xxxx /mnt
(3)运行inittab WAIT相关的脚本
(4)运行inittab ONCE相关的脚本
(5)运行inittab RESPAWN | ASKFIRST 相关的脚本 是否免密登录
::askfirst:-/bin/sh 按回车就直接进入shell
::respawn:/sbin/getty -L ttyS000 115200 vt100 -n root -I "Auto login as root ..."
::respawn:-/bin/login
之后运行/etc/profile