Linux kernel 关机的底层操作

来源:互联网 发布:罗马尼亚铁卫电影 知乎 编辑:程序博客网 时间:2024/06/08 12:52

Linux关机相关命令如:halt,shutdown,poweroff和reboot

其实它们底层都是调用名为reboot的system call,其具体实现是在内核目录的kernel/sys.c中的

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg)这个函数里,函数原型如下:

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,void __user *, arg){struct pid_namespace *pid_ns = task_active_pid_ns(current);char buffer[256];int ret = 0;/* We only trust the superuser with rebooting the system. */if (!ns_capable(pid_ns->user_ns, 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;/* * If pid namespaces are enabled and the current task is in a child * pid_namespace, the command is handled by reboot_pid_ns() which will * call do_exit(). */ret = reboot_pid_ns(pid_ns, cmd);if (ret)return ret;/* 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;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();do_exit(0);panic("cannot halt");case LINUX_REBOOT_CMD_POWER_OFF:kernel_power_off();do_exit(0);break;case LINUX_REBOOT_CMD_RESTART2:if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {ret = -EFAULT;break;}buffer[sizeof(buffer) - 1] = '\0';kernel_restart(buffer);break;#ifdef CONFIG_KEXECcase LINUX_REBOOT_CMD_KEXEC:ret = kernel_kexec();break;#endif#ifdef CONFIG_HIBERNATIONcase LINUX_REBOOT_CMD_SW_SUSPEND:ret = hibernate();break;#endifdefault:ret = -EINVAL;break;}mutex_unlock(&reboot_mutex);return ret;}

其中针对cmd有多个case,经过我在imx6平台上测试发现:

poweroff,halt和shutdown都是调用的 case LINUX_REBOOT_CMD_POWER_OFF

而reboot则是调用case LINUX_REBOOT_CMD_RESTART

这里以poweroff为例,会依次进行如下调用:

-->kernel_power_off()                         //kernel/sys.c

     -->kernel_shutdown_prepare   

     -->migrate_to_reboot_cpu

     -->syscore_shutdown

     -->machine_power_off               // 该函数根据具体平台而定,arm平台在arch/arm/kernel/process.c文件中



详细可以参考这篇文章http://www.wowotech.net/linux_kenrel/reboot.html

0 0
原创粉丝点击