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. 数据库开源框架之ormlite

    主页: http://ormlite.com/ 配置: 添加以下依赖 * compile 'com.j256.ormlite:ormlite-android:4.48' * compile 'com. ...

  2. 如何在GitHub上下载一部分文件(单个文件夹)

    Preface Github下的项目可能很大,里面有很多的子文件夹,我们可能只需要使用某个子目录下的资源,可以不用下载完整的repo就能使用. 例如,我想下载这个repo中的mnist_gan文件:h ...

  3. 关于ansbile

    YAML语法规则 规则一:缩进(一个缩进两空格,注意一定不用tab) 规则二:冒号(每个冒号后一定要有空格) 规则三:短横线 - (短横线后面要空格) 编写案例 ansible-playbook -- ...

  4. 基于durid的JDBCUtils工具类

    1.JDBCUtils类 package com.alphajuns.utils; import com.alibaba.druid.pool.DruidDataSourceFactory; impo ...

  5. Java并发编程之程序运行堆栈分析

    Java程序运行的堆栈分析 1.JVM运行时数据区 JVM通过加载class文件的数据来执行程序.JVM在运行时会划分不同的区域以存放数据.如下图所示: 线程共享部分:所有线程都能访问这块内存的数据, ...

  6. ES 知识点

    一.ES基于_version 进行乐观锁并发控制 post /index/type/id/_update?retry_on_conflict=5&version=6 1.内部版本号 第一次创建 ...

  7. 看我如何通过邮箱获取IP定位-复现

    环境准备:一台部署了phpstudy 的vps 脚本内容:get_ip.php 该脚本可以生成一个十分隐蔽的图片,并获取客户端的一些敏感信息. 代码内容如下: <?php //show_sour ...

  8. 【Python开发】查看数据类型

    import types aaa = 0 print type(aaa) if type(aaa) is types.IntType: print "the type of aaa is i ...

  9. docker-compose 部署elk+解决时间不对导致kibana找不到logstash定义的index + docker-compose安装

    1.拉代码 git clone https://github.com/deviantony/docker-elk.git 2.docker-compose配置文件 [root@host7 docker ...

  10. 【转帖】windows命令行中java和javac、javap使用详解(java编译命令)

    windows命令行中java和javac.javap使用详解(java编译命令) 更新时间:2014年03月23日 11:53:15   作者:    我要评论 http://www.jb51.ne ...