linux内核电源管理浅析

来源:互联网 发布:大秦帝国纵横知乎 编辑:程序博客网 时间:2024/05/20 01:09

一 重启(reboot)

应用程序通过reboot系统调用实现机器重启,reboot系统调用定义在kernel/sys.c文件中:

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg)
{

if (!capable(CAP_SYS_BOOT))
return -EPERM;

...............

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

...........

}

}

kernel_restart()调用machine_restart(),然后调用brcm_machine_restart_mips(),最后调用掉brcm_machine_restart():

void brcm_machine_restart(const char *command)
{
/* PR21527 - Fix SMP reboot problem */
#ifdef CONFIG_SMP
smp_send_stop();
udelay(10);
#endif


#ifdef BCHP_SUN_TOP_CTRL_SW_RESET
BDEV_WR_F_RB(SUN_TOP_CTRL_RESET_CTRL, master_reset_en, 1);
BDEV_WR_F_RB(SUN_TOP_CTRL_SW_RESET, chip_master_reset, 1);
#else
BDEV_WR_F_RB(SUN_TOP_CTRL_RESET_SOURCE_ENABLE,
sw_master_reset_enable, 1);
BDEV_WR_F_RB(SUN_TOP_CTRL_SW_MASTER_RESET, chip_master_reset, 1);
#endif


while (1)
;
}

设置软件复位寄存器,导致硬件复位。需要注意的是:执行该动作需要CAP_SYS_BOOT能力,所以在linux container中可以去掉该能力,调用reboot命令,只杀死该命名空间所有进程,导致init进程重启,看到的效果就是container重启了而系统主机不重启。


二 关机(halt和poweroff)

应用程序通过如下方式实现关机:

system("echo 1 > /sys/devices/platform/brcmstb/halt_mode");
system("halt");
其中echo 1 > /sys/devices/platform/brcmstb/halt_mode
broadcom增加的,详细可以查看driver/brcmstb/sysfs.c文件:

__ATTR(halt_mode, 0644, brcm_pm_show_halt_mode,
brcm_pm_store_halt_mode),

halt命令同样通过reboot系统调用实现,和上面reboot一样,调用kernel_halt()函数,然后调用machine_halt():

void brcm_machine_halt(void)
{
/* may be S3 cold boot */
brcm_pm_s3_cold_boot();


local_irq_disable();
while (1)
;
}

最后会调用到brcm_pm_s3_cold_boot()函数,该函数定义在driver/brcmstb/power.c文件中。

通过上面的代码可以看出,该函数是永远不会返回的,在唤醒后重新启动,S3_cold_boot是通过该模式实现的。

poweroff和halt实现几乎一样,也是通过reboot系统调用实现,调用kernel_power_off(),然后关闭掉其他的cpu核 (disable_nonboot_cpus()),最后调用machine_power_off(),该函数底层和machine_halt()实现方式一样。


三 挂机(suspend)

应用程序调用:

system("echo mem > /sys/power/state");  

实现方式为:调用pm_suspend()-->enter_state()-->suspend_devices_and_enter()-->suspend_enter()-->brcm_pm_enter()

S3_warm_boot通过该方式实现,特点是DDR自刷新,当唤醒时可以从进入待机的地方返回继续执行。


四 C_A_D

可以通过reboot系统调用关闭或者打开C_A_D功能。

当键盘按下ctrl+alt+delete组合键时,会调用fn_boot_it()函数,定义在drivers/tty/vt/keyboard.c文件中:

static void fn_boot_it(struct vc_data *vc)
{
ctrl_alt_del();
}

其中ctrl_alt_del()的定义为:

void ctrl_alt_del(void)
{
static DECLARE_WORK(cad_work, deferred_cad);


if (C_A_D)
schedule_work(&cad_work);
else
kill_cad_pid(SIGINT, 1);
}

在C_A_D打开时,将deferred_cad()放在workqueue上延迟运行,deferred_cad()函数的定义为:

static void deferred_cad(struct work_struct *dummy)
{
kernel_restart(NULL);
}

所以在这种情况下,按下ctrl+alt+delete组合键看到的效果就是机器重启了。

当C_A_D关闭时,调用的是kill_cad_pid(),进一步跟踪,很容易发现该函数实际就是给init进程发送了SIGINT信号,init进程收到该信号后杀死所有用户空间进程,然后重启init进程,这种情况下,按下ctrl+alt+delete组合键看到的效果就是机器重新注销登陆。

原创粉丝点击