http://www.xuebuyuan.com/736763.html

基于Linux与Busybox的Reboot命令流程分析

***************************************************************************************************************************
作者:EasyWave            
                     
                     
                     
  时间:2013.01.26

类别:Linux 内核系统源码分析                                                             声明:转载,请保留链接

注意:如有错误,欢迎指正。这些是我学习的日志文章......

***************************************************************************************************************************

一:Busyobx层的分析

这段时间,在忙到一个项目时,需要在busybox中用到reboot命令,开始在busybox中的shell中输入reboot命令,始终如下的信息,然后就停止在那里了,无法重启...为了彻底的弄明白这个问题,我在网络上找了很久,终于有个人写的一个reboot流程分析,我就借花献佛.在这里重新分析下busybox是如何运行这个命令,同时又是如何调用到Linux内核中的mach_reset中的arch_reset,当针对不同的ARM芯片时,作为Linux内核开发和驱动开发的朋友,对于这个流程还是一定要了解的。要不,出现问题,又如何找出问题呢。忘记了reboot的打印信息了,如下:

The system is going
down NOW !!

Sending SIGTERM to
all processes.

Sending SIGKILL to
all processes.

Please stand by while
rebooting the system.

Restarting system.

.

通过分析busybox1.20.0的代码可以看出在init.c中有这样一行的代码,如下:

int init_main(int
argc, char **argv) MAIN_EXTERNALLY_VISIBLE;

int init_main(int
argc UNUSED_PARAM, char **argv)

{

static const int magic[] = {

RB_HALT_SYSTEM,

RB_POWER_OFF,

RB_AUTOBOOT

};

static const smallint signals[] = {
SIGUSR1, SIGUSR2, SIGTERM };

......

/* struct sysinfo is linux-specific */

#ifdef __linux__

/* Make sure there is enough memory to
do something useful. */

if (ENABLE_SWAPONOFF) { //是否配置了swapoff命令

struct sysinfo info;

if (sysinfo(&info) == 0

&& (info.mem_unit ? info.mem_unit : 1)
* (long long)info.totalram < 1024*1024

) {

message(L_CONSOLE,
"Low memory, forcing swapon");

/* swapon -a
requires /proc typically */

new_init_action(SYSINIT,
"mount -t proc proc /proc", "");

/* Try to turn on
swap */

new_init_action(SYSINIT,
"swapon -a", "");

run_actions(SYSINIT);   /* wait and removing */

}

}

#endif

......

/* Make the command
line just say "init"  - thats
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)

memset(*argv, 0,
strlen(*argv));

/* Set up signal handlers */

/* 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

signal(SIGQUIT,
restart_handler); /* re-exec another init */ //看到这个restart_handler函数,这是我们需要分析的

/* 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;

/* NB: sa_flags doesn't have
SA_RESTART.

* It must be able to interrupt wait().

*/

sigaction_set(SIGTSTP,
&sa); /* pause */

/* Does not work as
intended, at least in 2.6.20.

* SIGSTOP is simply ignored by init:

*/

sigaction_set(SIGSTOP,
&sa); /* pause */

/* SIGINT (Ctrl-Alt-Del)
must interrupt wait(),

* setting handler without SA_RESTART flag.

*/

bb_signals_recursive_norestart((1
<< SIGINT), record_signo);

}

......

}

单独拿出halt_reboot_pwoff和restart_handler这个函数来看看

/* The
SIGUSR[12]/SIGTERM handler */

static void
halt_reboot_pwoff(int sig) NORETURN;

static void
halt_reboot_pwoff(int sig)

{

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 */

}

restart_handler函数如下:

/* Handler for QUIT -
exec "restart" action,

* else (no such action defined) do nothing */

static void
restart_handler(int sig UNUSED_PARAM)

{

struct init_action *a;

for (a = init_action_list; a; a =
a->next) {

if (!(a->action_type
& RESTART))

continue;

/* Starting from here, we
won't return.

* Thus don't need to worry about preserving errno

* and such.

*/

reset_sighandlers_and_unblock_sigs();

run_shutdown_and_kill_processes();

#ifdef RB_ENABLE_CAD

/* Allow Ctrl-Alt-Del to
reboot the system.

* This is how kernel sets it up for init, we
follow suit.

*/

reboot(RB_ENABLE_CAD); /*
misnomer */

#endif

if
(open_stdio_to_tty(a->terminal)) {

dbg_message(L_CONSOLE,
"Trying to re-exec %s", a->command);

/* Theoretically
should be safe.

* But in practice, kernel bugs may leave

* unkillable processes, and wait() may block
forever.

* Oh well. Hoping "new" init won't
be too surprised

* by having children it didn't create.

*/

//while
(wait(NULL) > 0)

//        continue;

init_exec(a->command);

}

/* Open or exec failed */

pause_and_low_level_reboot(RB_HALT_SYSTEM);

/* not reached */

}

}

通过分析,我们看到他们都会有调用这两个函数:reset_sighandlers_and_unblock_sigs();以及 run_shutdown_and_kill_processes();,我们重点关注如下这个函数:

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 */

}

嘿嘿,终于看到了上面的打印信息:The
system is going down NOW !! 以及Sending SIGTERM to all
processes. 同时在上面的halt_reboot_pwoff和restart_handler中都会调用这样一个函数,如下:

static void
pause_and_low_level_reboot(unsigned magic) NORETURN;

static void
pause_and_low_level_reboot(unsigned magic)

{

pid_t pid;

/* Allow time for last message to
reach serial console, etc */

sleep(1);

/* We have to fork here, since the
kernel calls do_exit(EXIT_SUCCESS)

* in linux/kernel/sys.c, which can cause the
machine to panic when

* the init process exits... */

pid = vfork();

if (pid == 0) { /* child */

reboot(magic);

_exit(EXIT_SUCCESS);

}

while (1)

sleep(1);

}

看到了吗?有一个reboot(magic)函数,对于vfork函数,请参考fork函数。这里不多说了.... 我们现在来看看reboot.h文件,如下:

/*

* Definitions related to the reboot() system
call,

* shared between init.c and halt.c.

*/

#include
<sys/reboot.h>

#ifndef
RB_HALT_SYSTEM

# if
defined(__linux__)

#  define RB_HALT_SYSTEM  0xcdef0123

#  define RB_ENABLE_CAD   0x89abcdef

#  define RB_DISABLE_CAD  0

#  define RB_POWER_OFF    0x4321fedc

#  define RB_AUTOBOOT     0x01234567

# elif
defined(RB_HALT)

#  define RB_HALT_SYSTEM  RB_HALT

# endif

#endif

/* Stop system and
switch power off if possible.  */

#ifndef RB_POWER_OFF

# if
defined(RB_POWERDOWN)

#  define RB_POWER_OFF  RB_POWERDOWN

# elif
defined(__linux__)

#  define RB_POWER_OFF  0x4321fedc

# else

#  warning "poweroff unsupported, using
halt as fallback"

#  define RB_POWER_OFF  RB_HALT_SYSTEM

# endif

#endif

而在linux的内核中的定义如下:

busybox和linux内核中的REBOOT的定义值是一样的。看到了没有了。这个很重要的哦,否则busybox是无法调用linux内核的reboot函数。

二:Linux内核层的分析

Linux内核是如何衔接busybox的reboot函数的呢,如下代码:

/*

* 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;

lock_kernel();

switch (cmd) {

case LINUX_REBOOT_CMD_RESTART:

kernel_restart(NULL); //这个就是重新启动Linx的命令

break;

case LINUX_REBOOT_CMD_CAD_ON:

C_A_D = 1;

break;

case LINUX_REBOOT_CMD_CAD_OFF:

C_A_D = 0;

break;

case LINUX_REBOOT_CMD_HALT:

kernel_halt();

unlock_kernel();

do_exit(0);

panic("cannot
halt");

case LINUX_REBOOT_CMD_POWER_OFF:

kernel_power_off();

unlock_kernel();

do_exit(0);

break;

case LINUX_REBOOT_CMD_RESTART2:

if
(strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {

unlock_kernel();

return -EFAULT;

}

buffer[sizeof(buffer) - 1] =
'\0';

kernel_restart(buffer);

break;

#ifdef CONFIG_KEXEC

case LINUX_REBOOT_CMD_KEXEC:

ret = kernel_kexec();

break;

#endif

#ifdef
CONFIG_HIBERNATION

case LINUX_REBOOT_CMD_SW_SUSPEND:

ret = hibernate();

break;

#endif

default:

ret = -EINVAL;

break;

}

unlock_kernel();

return ret;

}

继续跟踪kernel_restart()函数,如下:

最终会调用一个machine_restart(cmd)函数,这个是跟具体的芯片有很大的关系的,我们进一步的分析如下:

看到了吗,最终是调用arch_reset来复位整个系统的。同时我们也看到了S3C2440的reset的函数如下:

在arm_pm_restart = s3c24xx_pm_restart()函数,最终也是调用arm_machine_restart(mod, cmd)来实现的。而在arm_machine_restart()函数中,最终也是调用arch_reset()函数来实现,而这个函数是在哪里呢。在S3C2440没有看到arch_reset函数的实现,因此从S3C2410中找到了如下的代码,请继续看下面的代码:

终于看到了arch_reset函数,最终是采用S3C2410或者S3C2440的WatchDog来实现reboot的命令的。大家可以想想,busybox的poweroff命令,是如何实现通过Linux系统关闭整个系统的电源呢,其实很简单,只需要实现下面的函数中的pm_power_off的回调函数即可。

我们可以通过一个GPIO来控制整个系统的电源,而通过上面的pm_power_off的回调函数来实现,只需要在pm_power_off函数对GPIO进行操作就可以了。你看不是很简单吗?

====================================================================

at91sam9g10复位过程:

1) at91_arch_reset() = at91sam9261_reset();

kernel/arch/arm/mach-at91/at91sam9261.c

/* --------------------------------------------------------------------

*  AT91SAM9261 processor initialization

* -------------------------------------------------------------------- */

void __init at91sam9261_initialize(unsigned long main_clock)

{

/* Map peripherals */

iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));

if (cpu_is_at91sam9g10())

iotable_init(at91sam9g10_sram_desc, ARRAY_SIZE(at91sam9g10_sram_desc));

else

iotable_init(at91sam9261_sram_desc, ARRAY_SIZE(at91sam9261_sram_desc));

at91_arch_reset = at91sam9261_reset;

pm_power_off = at91sam9261_poweroff;

at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)

| (1 << AT91SAM9261_ID_IRQ2);

/* Init clock subsystem */

at91_clock_init(main_clock);

/* Register the processor-specific clocks */

at91sam9261_register_clocks();

/* Register GPIO subsystem */

at91_gpio_init(at91sam9261_gpio, 3);

}

static void at91sam9261_reset(void)

{

#ifdef CONFIG_ARCH_AT91SAM9G10

at91_lcdc_write(ATMEL_LCDC_PWRCON, 1 << ATMEL_LCDC_GUARDT_OFFSET);

while (at91_lcdc_read(ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)

msleep(10);

at91_lcdc_write(ATMEL_LCDC_DMACON, 0);

while (at91_lcdc_read(ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)

msleep(10);

local_irq_disable();

#endif

printk(KERN_ERR "software rest!!!\n") ;

// at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);

at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY | AT91_RSTC_ERSTL);    at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST |AT91_RSTC_EXTRST );

}

static void at91sam9261_poweroff(void)

{

at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);

}

2) arch_reset();

kernel/arch/arm/mach-at91/include/mach/system.h

static inline void arch_reset(char mode, const char *cmd)

{

/* call the CPU-specific reset function */

if (at91_arch_reset)

(at91_arch_reset)();

}

3) arm_machine_restart();

arch/arm/kernel/process.c

void arm_machine_restart(char mode, const char *cmd)

{

printk("in: %s:%s !\n",__FILE__,__FUNCTION__);

/*

* Clean and disable cache, and turn off interrupts

*/

cpu_proc_fin();

/*

* Tell the mm system that we are going to reboot -

* we may need it to insert some 1:1 mappings so that

* soft boot works.

*/

setup_mm_for_reboot(mode);

/*

* Now call the architecture specific reboot code.

*/

  arch_reset(mode, cmd);

/*

* Whoops - the architecture was unable to reboot.

* Tell the user!

*/

mdelay(1000);

printk("Reboot failed -- System halted\n");

while (1);

}

4) machine_restart()

kernel/arch/arm/kernel/process.c

void machine_power_off(void)

{

if (pm_power_off)

pm_power_off();

}

void machine_restart(char *cmd)

{

printk("in:%s:%s\n",__FILE__,__FUNCTION__);

        arm_pm_restart(reboot_mode, cmd);

}

void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;

EXPORT_SYMBOL_GPL(arm_pm_restart);

5) kernel_restart()

kernel/kernel/sys.c

void kernel_restart_prepare(char *cmd)

{

blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);

system_state = SYSTEM_RESTART;

device_shutdown();

sysdev_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);

    machine_restart(cmd);

}

EXPORT_SYMBOL_GPL(kernel_restart);

6) SYSCALL_DEFINE4()

kernel/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;

lock_kernel();

switch (cmd) {

case LINUX_REBOOT_CMD_RESTART:

            printk("in %s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__)  ;

            kernel_restart(NULL);

break;

case LINUX_REBOOT_CMD_CAD_ON:

C_A_D = 1;

break;

case LINUX_REBOOT_CMD_CAD_OFF:

C_A_D = 0;

break;

case LINUX_REBOOT_CMD_HALT:

kernel_halt();

unlock_kernel();

do_exit(0);

panic("cannot halt");

case LINUX_REBOOT_CMD_POWER_OFF:

kernel_power_off();

unlock_kernel();

do_exit(0);

break;

case LINUX_REBOOT_CMD_RESTART2:

if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {

unlock_kernel();

return -EFAULT;

}

buffer[sizeof(buffer) - 1] = '\0';

printk("in %s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__)  ;

kernel_restart(buffer);

break;

#ifdef CONFIG_KEXEC

case LINUX_REBOOT_CMD_KEXEC:

ret = kernel_kexec();

break;

#endif

#ifdef CONFIG_HIBERNATION

case LINUX_REBOOT_CMD_SW_SUSPEND:

ret = hibernate();

break;

#endif

default:

ret = -EINVAL;

break;

}

unlock_kernel();

return ret;

}

7) kernel/include/linux/reboot.h

/*

* Magic values required to use _reboot() system call.

*/

#define LINUX_REBOOT_MAGIC1 0xfee1dead

#define LINUX_REBOOT_MAGIC2 672274793

#define LINUX_REBOOT_MAGIC2A    85072278

#define LINUX_REBOOT_MAGIC2B    369367448

#define LINUX_REBOOT_MAGIC2C    537993216

/*

* Commands accepted by the _reboot() system call.

*

* RESTART     Restart system using default command and mode.

* HALT        Stop OS and give system control to ROM monitor, if any.

* CAD_ON      Ctrl-Alt-Del sequence causes RESTART command.

* CAD_OFF     Ctrl-Alt-Del sequence sends SIGINT to init task.

* POWER_OFF   Stop OS and remove all power from system, if possible.

* RESTART2    Restart system using given command string.

* SW_SUSPEND  Suspend system using software suspend if compiled in.

* KEXEC       Restart system using a previously loaded Linux kernel

*/

#define LINUX_REBOOT_CMD_RESTART    0x01234567

#define LINUX_REBOOT_CMD_HALT       0xCDEF0123

#define LINUX_REBOOT_CMD_CAD_ON     0x89ABCDEF

#define LINUX_REBOOT_CMD_CAD_OFF    0x00000000

#define LINUX_REBOOT_CMD_POWER_OFF  0x4321FEDC

#define LINUX_REBOOT_CMD_RESTART2   0xA1B2C3D4

#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2

#define LINUX_REBOOT_CMD_KEXEC      0x45584543

8) busybox/init/reboot.h

#include <sys/reboot.h>

#ifndef RB_HALT_SYSTEM

# if defined(__linux__)

#  define RB_HALT_SYSTEM  0xcdef0123

#  define RB_ENABLE_CAD   0x89abcdef

#  define RB_DISABLE_CAD  0

#  define RB_POWER_OFF    0x4321fedc

#  define RB_AUTOBOOT     0x01234567

# elif defined(RB_HALT)

#  define RB_HALT_SYSTEM  RB_HALT

# endif

#endif

/* Stop system and switch power off if possible.  */

#ifndef RB_POWER_OFF

# if defined(RB_POWERDOWN)

#  define RB_POWER_OFF  RB_POWERDOWN

# elif defined(__linux__)

#  define RB_POWER_OFF  0x4321fedc

# else

#  warning "poweroff unsupported, using halt as fallback"

#  define RB_POWER_OFF  RB_HALT_SYSTEM

# endif

#endif

9) pause_and_low_level_reboot()

busybox/init/init.c

static void pause_and_low_level_reboot(unsigned magic) NORETURN;

static void pause_and_low_level_reboot(unsigned magic)

{

pid_t pid;

/* Allow time for last message to reach serial console, etc */

sleep(1);

/* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS)

* in linux/kernel/sys.c, which can cause the machine to panic when

* the init process exits... */

pid = vfork();

if (pid == 0) { /* child */

    reboot(magic);

_exit(EXIT_SUCCESS);

}

while (1)

sleep(1);

}

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 */

}

/* The SIGPWR/SIGUSR[12]/SIGTERM handler */

static void halt_reboot_pwoff(int sig) NORETURN;

static void halt_reboot_pwoff(int sig)

{

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 */

}

/* Handler for QUIT - exec "restart" action,

* else (no such action defined) do nothing */

static void exec_restart_action(void)

{

struct init_action *a;

for (a = init_action_list; a; a = a->next) {

if (!(a->action_type & RESTART))

continue;

/* Starting from here, we won't return.

* Thus don't need to worry about preserving errno

* and such.

*/

reset_sighandlers_and_unblock_sigs();

run_shutdown_and_kill_processes();

#ifdef RB_ENABLE_CAD

/* Allow Ctrl-Alt-Del to reboot the system.

* This is how kernel sets it up for init, we follow suit.

*/

reboot(RB_ENABLE_CAD); /* misnomer */

#endif

if (open_stdio_to_tty(a->terminal)) {

dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command);

/* Theoretically should be safe.

* But in practice, kernel bugs may leave

* unkillable processes, and wait() may block forever.

* Oh well. Hoping "new" init won't be too surprised

* by having children it didn't create.

*/

//while (wait(NULL) > 0)

//  continue;

init_exec(a->command);

}

/* Open or exec failed */

pause_and_low_level_reboot(RB_HALT_SYSTEM);

/* not reached */

}

}

基于linux与busybox的reboot命令流程分析的更多相关文章

  1. 一只简单的网络爬虫(基于linux C/C++)————主事件流程

    该爬虫的主事件流程大致如下: 1.获取命令行参数,执行相应操作 2.读取配置文件,解析得到各种设置 3.载入各种模块 4.种子入队,开启DNS解析线程(原始队列不为空时解析) 5.创建epoll,开启 ...

  2. 配置Linux Kernel时make menuconfig执行流程分析

       在编译内核前,一般是根据已有的配置文件(一般在内核根目录下的arch/arm/configs/文件夹下,把该目录下的xxx_defconfig文件拷贝到内核根目录下,并重命名为.config)来 ...

  3. 第一次作业:基于Linux操作系统深入源码进程模型分析

    1.Linux操作系统的简易介绍 Linux系统一般有4个主要部分:内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使 ...

  4. 基于Linux C的socketEthereal程序和Package分析 (一个)

     执行测试平台:CentOS 6.5发行版,内核版本号3.11 1. Linux抓包源程序 在OSI七层模型中.网卡工作在物理层和数据链路层的MAC子层. 进行网络通信时.源主机通过socket( ...

  5. 【转载】基于Linux命令行KVM虚拟机的安装配置与基本使用

    基于Linux命令行KVM虚拟机的安装配置与基本使用 https://alex0227.github.io/2018/06/06/%E5%9F%BA%E4%BA%8ELinux%E5%91%BD%E4 ...

  6. Linux命令学习总结:reboot命令

    命令简介: 该命令用来重启Linux系统.相当于Windows系统中的restart命令. 命令语法: /sbin/reboot [-n] [-w] [-d] [-f] [-i] 或 reboot [ ...

  7. 【摘】linux之shutdown、halt和reboot命令详解

    在重新启动Linux系统的同时把内存中的信息写入硬盘,应使用()命令实现 #shutdown -r now #halt #reboot #init3 正确答案:A   在linux命令中reboot是 ...

  8. 7个基于Linux命令行的文件下载和网站浏览工具

    7个基于Linux命令行的文件下载和网站浏览工具 时间:2015-06-01 09:36来源:linux.cn 编辑:linux.cn 点击: 2282 次 Linux命令行是GNU/Linux中最神 ...

  9. 安装基于 Linux 发行版的重要事项(流程指引)

    安装基于 Linux 发行版的重要事项(Install important issues based on the Linux distribution. (Process guidance)) 1. ...

随机推荐

  1. Jmeter建立一个扩展LDAP测试计划

    Jmeter建立一个扩展LDAP测试计划 添加用户 第一步你想做的每一个JMeter测试计划是添加一个线程组元素. 线程组告诉JMeter的用户数量你想模拟,用户应该发送的次数 请求,他们应该发送的请 ...

  2. Linux Openssh源码升级

    telnet服务 yum install -y telnet-server xinetd systemctl start xinetd systemctl start telnet.socket #监 ...

  3. Redis ==> 高级

    一.发布订阅 Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. Redis 客户端可以订阅任意数量的频道. 下图展示了频道 channel ...

  4. Numpy 库

    可以直接通过pip安装. pip install numpy 1 NumPy的数值类型 每一种数据类型都有相应的转换函数.使用dtype属性可以查看数组的数据类型.如下. 2 数组操作 使用arang ...

  5. //C#中的访问数据符

    [在命名空间里面直接定义类型只能用internal  或 public ] [要被同个解决方案内 其他项目访问 ,加引用 导命名空间]. [类的默认修饰符是internal] 1.Private    ...

  6. Autofac实现AOP拦截

    本文主要是详解一下在ASP.NET Core中,采用替换后的Autofac来实现AOP拦截. Aspect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题.AO ...

  7. Misc题目

    @freebuff教程https://www.freebuf.com/column/196815.html @巅峰极客wp https://www.anquanke.com/post/id/18914 ...

  8. Java架构师 -- 知识库

    1,CSDN知识库: http://lib.csdn.net/base/architecture 2,淘宝

  9. Laravel-Admin图片上传时的问题

    关于laravel-admin进入有图片上传页面时,会提示未配置存储路径等信息.此时需要去配置. 查看config/admin.php里面有 'upload' => [ // Disk in ` ...

  10. 【STM32】NVIC中断优先级管理

    (1)NVIC中断优先级分组 1>,CM4内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且 具有256级的可编程中断设置. 2>,STM32F4并没有使用CM4的内核 ...