BusyBox is a collection of commands such as LS and CP.
When LS is executed, the BusyBox LS is actually executed.
When the CP is executed, the BusyBox CP is actually executed
Before analyzing the INIT program, let us recall our goal: U-boot boot the kernel, the kernel launches the application, how the kernel launches the application, and the kernel launches the INIT process, which is located in/sbin/init. Our ultimate goal is to start the client program, that is, if you are a mobile phone, want to start a mobile phone program, if it is to do monitoring, then start a monitoring program. Customers have different, but all use the Linux system, then how to differentiate it?
There should be something like this in the INIT program:
Read the configuration file and specify the application to be executed later;
Parse the configuration file;
Execute the user's program according to the configuration file;
BusyBox->init_main
Parse_inittab ();
File = fopen (INITTAB, "R");//#define INITTAB "/etc/inittab" to open the configuration file/etc/inittab
New_init_action (a->action, command, id); A. Create a init_action structure and populate it;
B. Place the init_action structure into the init_action_list list;
Run_actions (Sysinit);
static void run_actions (int action)
{
struct init_action *a, *tmp;
WAITFOR (A, 0); Execute the application and wait for it to finish executing
Run (a); Create Process subprocess
Wpid = Waitpid (runpid, &status, 0); Wait for it to end
Delete_init_action (a); Delete A in the init_action_list linked list
}
Run_actions (WAIT)
static void run_actions (int action)
{
struct init_action *a, *tmp;
WAITFOR (A, 0); Execute the application and wait for it to finish executing
Run (a); Create Process subprocess
Wpid = Waitpid (runpid, &status, 0); Wait for it to end
Delete_init_action (a); Delete A in the init_action_list linked list
}
Run_actions (ONCE)
Run (a); Create Process subprocess
Delete_init_action (a); Does not wait for the end, just delete a in the Init_action_list list
while (1) {
Run_actions (respawn)
if (A->pid = = 0) {
A->pid = run (a);
}
Run_actions (Askfirst);
if (A->pid = = 0) {
A->pid = run (a);
}
Wpid = Wait (NULL);//wait for the child process to exit
while (Wpid > 0) {
a->pid = 0; After exiting, set the PID equal to 0
}
}
Under/etc/inittab file control, the behavior of the INIT process is summarized as follows:
A. At the beginning of the system startup, the Init process starts with the <action> for Sysinit, wait, and once three kinds of sub-processes;
B. During the system's normal operation, the Init process starts with <action> for two types of respawn, Askfirst, and monitors them, discovering that a child process is restarted when it exits
C. When the system exits, the execution <action> is shutdown, restart, Ctrlaltdel of the three types of sub-processes (one or all)
Minimal root file system:
/dev/console/dev/null in the BusyBox init program, you will also check if the device is open and use/dev/null if it cannot be opened.
Init from BusyBox
/etc/inittab
The application specified in the configuration file
C Library
Assuming there is no configuration file, exit the configuration file from the default new_init_action:
#inittab的格式:
#<id>:<runlevels>:<action>:<process>
#id =>/dev/id, eventually used as a terminal. stdin, stdout, stderr
#runlevels: <runlevels> can be ignored completely;: The Runlevels field is completely ignored
#action: Timing of execution
<action>: Sysinit, respawn, Askfirst, wait, once,
Restart, Ctrlaltdel, and shutdown.
#process: Application or Script
/* Reboot on Ctrl-alt-del */
New_init_action (Ctrlaltdel, "reboot", "" ");
Launched:: Ctrlaltdel:reboot
/* Umount all filesystems on Halt/reboot */
New_init_action (SHUTDOWN, "Umount-a-R", "");
launch :: shutdown:umount-a-R
/* Prepare to restart Init when a HUP is received */
new_init _action (RESTART, "Init", "");
Launch::: 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);
Launched in sequence:: askfirst:-/bin/sh
/dev/tty2::askfirst:-/bin/sh
/dev/tty3::askfirst:-/bin/sh
/dev/tty4:: askfirst:-/bin/sh
/* Sysinit */
New_init_action (Sysinit, Init_script, "");
#define INIT_SCRIPT "/etc/init.d/rcs"
Launched:: sysinit:/etc/init.d/rcs
Take New_init_action (Askfirst, Bb_default_login_shell, vc_2) and analyze for example:
#define Libbb_default_login_shell "-/bin/sh",
# define VC_2 "/dev/tty2" so New_init_action (Askfirst, Bb_default_login_shell, vc_2) becomes
New_init_action (Askfirst, "-/bin/sh", "/dev/tty2")
static void new_init_action (int action, const char *command, const char *cons) This function has a struct init_action and a look at the members of this struct:
struct Init_action {
struct Init_action *next;
int action; Timing of execution
pid_t pid;
Char command[init_buffs_size]; application or script
Char Terminal[console_name_size]; terminal
};
So you can infer that the new_init_action function does these things:
A. Create a init_action structure and populate it;
B. Place the init_action structure into the init_action_list list;
Analysis of the INIT process for building the root file system