http://blog.csdn.net/muge0913/article/details/7518576
系统调用的内容到这里已经讲述了很多,该到去kernel中窥看一个服务例程具体实现的时候了。在linux中关机和重启命令有shutdown,reboot,init,poweroff,halt,telinit。它们都是通过sys_reboot来实现的。在kernel/sys.c中。
/* *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. */ /* *检查调用者是否有合法权限。capable函数用于检查是否有操作指定资源的权限, *如果它返回非零值,则调用者有权进行操作,否则无权操作. *capable(CAP_SYS_BOOT)即检查调用者是否有权限使用reboot系统调用 */ if (!capable(CAP_SYS_BOOT)) return -EPERM; /* For safety, we require "magic" arguments. */ /* *通过对两个参数magic1和magic2的检测,判断reboot系统调用是不是被偶然调用到的。 *如果reboot系统调用是被偶然调用的, *那么参数magic1和magic2几乎不可能同时满足预定义的这几个数字的集合。 */ 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); /*sys_reboot()对调用者的各种使用情况进行区分。 *为LINUX_REBOOT_CMD_RESTART时,kernel_restart()将打印出"Restarting system."消息, *然后调用machine_restart函数重新启动系统。 *为LINUX_REBOOT_CMD_CAD_ON或LINUX_REBOOT_CMD_CAD_OFF时, *分别允许或禁止Ctrl+Alt+Del组合键。 *我们还可以在/etc/inittab文件指定是否可以使用Ctrl+Alt+Del组合键来关闭并重启系统。 *如果希望完全禁止这个功能,需要将/etc/inittab文件中的相应一行注释掉。 *为LINUX_REBOOT_CMD_HALT时,打印出"System halted."消息,和LINUX_REBOOT_CMD_RESTART情况下类似, *但只是暂停系统而不是将其重新启动。为LINUX_REBOOT_CMD_POWER_OFF时,打印出"Power down."消息,然后关闭机器电源。 *为LINUX_REBOOT_CMD_RESTART2时,接收命令字符串,该字符串说明了系统应该如何关闭。 *LINUX_REBOOT_CMD_SW_SUSPEND用于使系统休眠。 */ 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_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; } mutex_unlock(&reboot_mutex); return ret; }