busybox

busybox inittab


更新記錄

item note
20150917 第一版

目錄


inittab 表格 格式如下

1
2
3
4
- Format for each entry: <id>:<runlevels>:<action>:<process>
<id>: busybox是用來指定ttyx,目前無用到
<runlevels>: busybox是不支援此功能,目前無用到
<action>: Valid actions include: sysinit, respawn, askfirst, wait, once,restart, ctrlaltdel, and shutdown.

實際板端範例如下 (/etc/inittab)

1
2
3
4
5
6
7
8
9
10
# Example of how to put a getty on a serial line (for a terminal)
::respawn:/sbin/getty -L ttyS000 115200 vt100 -n root -I "Auto login as root ..."

# Stuff to do when restarting the init process
::restart:/sbin/init

# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

以init為第1個process,其它的都是由init長出來的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ps
PID USER VSZ STAT COMMAND
1 root 3176 S init
2 root 0 SW [kthreadd]
3 root 0 SW [ksoftirqd/0]
4 root 0 SW [kworker/0:0]
5 root 0 SW [kworker/u:0]
6 root 0 SW [migration/0]
7 root 0 SW [migration/1]
8 root 0 SW [kworker/1:0]
9 root 0 SW [ksoftirqd/1]
10 root 0 SW< [khelper]
11 root 0 SW [kdevtmpfs]
12 root 0 SW [kworker/u:1]
173 root 0 SW [sync_supers]

手動reboot程序如下

  • 行號2是由run_shutdown_and_kill_processes呼叫run_actions(SHUTDOWN)
  • 行號3-5是由run_shutdown_and_kill_processes打印出來的
  • run_actions 跑的是init_action_list內容,此內容由/etc/inittab建立
1
2
3
4
5
# reboot
# umount: devtmpfs busy - remounted read-only
The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL toRestarting system.

busybox reboot程序

reboot(SIGTERM)訊號由halt_reboot_pwoff處里

1
2
3
4
5
6
7
8
9
10
11
12
int init_main(int argc UNUSED_PARAM, char **argv)
{
...
/* Set up signal handlers */
if (!DEBUG_INIT) {
struct sigaction sa;

bb_signals(0
+ (1 << SIGUSR1) /* halt */
+ (1 << SIGTERM) /* reboot */
+ (1 << SIGUSR2) /* poweroff */
, halt_reboot_pwoff);
  • halt_reboot_pwoff 呼叫 run_shutdown_and_kill_processes打印出reboot訊息
  • halt_reboot_pwoff 最後呼叫 pause_and_low_level_reboot(RB_AUTOBOOT) //RB_AUTOBOOT = 0x01234567,
  • pause_and_low_level_reboot:
    執行reboot(magic);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* The SIGUSR[12]/SIGTERM handler */
static void halt_reboot_pwoff(int sig) NORETURN;
{
const char *m;
unsigned rb;

/* We may call run() and it unmasks signals,
* including the one masked inside this signal handler.
* Testcase which would start multiple reboot scripts:
* while true; do reboot; done
* Preventing it:
*/
reset_sighandlers_and_unblock_sigs();

run_shutdown_and_kill_processes();

m = "halt";
rb = RB_HALT_SYSTEM;
if (sig == SIGTERM) {
m = "reboot";
rb = RB_AUTOBOOT;
} else if (sig == SIGUSR2) {
m = "poweroff";
rb = RB_POWER_OFF;
}
message(L_CONSOLE, "Requesting system %s", m);
pause_and_low_level_reboot(rb);
/* not reached */

run_shutdown_and_kill_processes抓印出訊息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void run_shutdown_and_kill_processes(void)
{
/* Run everything to be run at "shutdown". This is done _prior_
* to killing everything, in case people wish to use scripts to
* shut things down gracefully... */
run_actions(SHUTDOWN);

message(L_CONSOLE | L_LOG, "The system is going down NOW!");

/* Send signals to every process _except_ pid 1 */
kill(-1, SIGTERM);
message(L_CONSOLE | L_LOG, "Sent SIG%s to all processes", "TERM");
sync();
sleep(1);

kill(-1, SIGKILL);
message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
sync();
/*sleep(1); - callers take care about making a pause */
}

kernel reboot訊息

  • kernel使用LINUX_REBOOT_CMD_RESTART對照由busybox傳來的(RB_AUTOBOOT = 0x01234567) reboot 訊息
  • 此時kernel會執行 kernel_restart(NULL);
  • 先執行 kernel_restart_prepare此時會call每個device的shutdown (如spi shutdown)
  • 最後machine_restart(NULL),設定cpu register 軟啟動

SYSCALL_DEFINE4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
include/linux/reboot.h:#define  LINUX_REBOOT_CMD_RESTART        0x01234567

kernel/sys.c

/*
* Reboot system call: for obvious reasons only root may call it,
* and even root needs to set up some magic numbers in the registers
* so that some mistake won't make this reboot the whole machine.
* You can also set the meaning of the ctrl-alt-del-key here.
*
* reboot doesn't sync: do that yourself before calling this.
*/
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg)
{
char buffer[256];
int ret = 0;

/* We only trust the superuser with rebooting the system. */
if (!capable(CAP_SYS_BOOT))
return -EPERM;

/* For safety, we require "magic" arguments. */
if (magic1 != LINUX_REBOOT_MAGIC1 ||
(magic2 != LINUX_REBOOT_MAGIC2 &&
magic2 != LINUX_REBOOT_MAGIC2A &&
magic2 != LINUX_REBOOT_MAGIC2B &&
magic2 != LINUX_REBOOT_MAGIC2C))
return -EINVAL;

/* Instead of trying to make the power_off code look like
* halt when pm_power_off is not set do it the easy way.
*/
if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
cmd = LINUX_REBOOT_CMD_HALT;

mutex_lock(&reboot_mutex);
switch (cmd) {
case LINUX_REBOOT_CMD_RESTART:
kernel_restart(NULL);
break;

kernel_restart_prepare

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void kernel_restart_prepare(char *cmd)
{
blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
system_state = SYSTEM_RESTART;
usermodehelper_disable();
device_shutdown();
syscore_shutdown();
}

/**
* kernel_restart - reboot the system
* @cmd: pointer to buffer containing command to execute for restart
* or %NULL
*
* Shutdown everything and perform a clean reboot.
* This is not safe to call in interrupt context.
*/
void kernel_restart(char *cmd)
{
kernel_restart_prepare(cmd);
if (!cmd)
printk(KERN_EMERG "Restarting system.\n");
else
printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);
kmsg_dump(KMSG_DUMP_RESTART);
machine_restart(cmd);
}
EXPORT_SYMBOL_GPL(kernel_restart);

其它說明

/etc/inittab

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# cat /etc/inittab 
# /etc/inittab init(8) configuration for BusyBox
#
# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
#
#
# Note, BusyBox init doesn't support runlevels. The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use sysvinit.
#
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# <id>: WARNING: This field has a non-traditional meaning for BusyBox init!
#
# The id field is used by BusyBox init to specify the controlling tty for
# the specified process to run on. The contents of this field are
# appended to "/dev/" and used as-is. There is no need for this field to
# be unique, although if it isn't you may have strange results. If this
# field is left blank, it is completely ignored. Also note that if
# BusyBox detects that a serial console is in use, then all entries
# containing non-empty id fields will _not_ be run. BusyBox init does
# nothing with utmp. We don't need no stinkin' utmp.
#
# <runlevels>: The runlevels field is completely ignored.
#
# <action>: Valid actions include: sysinit, respawn, askfirst, wait, once,
# restart, ctrlaltdel, and shutdown.
#
# Note: askfirst acts just like respawn, but before running the specified
# process it displays the line "Please press Enter to activate this
# console." and then waits for the user to press enter before starting
# the specified process.
#
# Note: unrecognised actions (like initdefault) will cause init to emit
# an error message, and then go along with its business.
#
# <process>: Specifies the process to be executed and it's command line.
#
# Note: BusyBox init works just fine without an inittab. If no inittab is
# found, it has the following default behavior:
# ::sysinit:/etc/init.d/rcS
# ::askfirst:/bin/sh
# ::ctrlaltdel:/sbin/reboot
# ::shutdown:/sbin/swapoff -a
# ::shutdown:/bin/umount -a -r
# ::restart:/sbin/init
#
# if it detects that /dev/console is _not_ a serial console, it will
# also run:
# tty2::askfirst:/bin/sh
# tty3::askfirst:/bin/sh
# tty4::askfirst:/bin/sh
#
# Boot-time system configuration/initialization script.
# This is run first except when booting in single-user mode.

#
::sysinit:/etc/init.d/rcS

# /bin/sh invocations on selected ttys
#
# Note below that we prefix the shell commands with a "-" to indicate to the
# shell that it is supposed to be a login shell. Normally this is handled by
# login, but since we are bypassing login in this case, BusyBox lets you do
# this yourself...
#
# Start an "askfirst" shell on the console (whatever that may be)
#::askfirst:-/bin/sh
# Start an "askfirst" shell on /dev/tty2-4
# tty2::askfirst:-/bin/sh
# tty3::askfirst:-/bin/sh
# tty4::askfirst:-/bin/sh

# /sbin/getty invocations for selected ttys
# tty4::respawn:/sbin/getty 38400 tty5
# tty5::respawn:/sbin/getty 38400 tty6

參考來源