系統調用的內容到這裡已經講述了很多,該到去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. *查看本欄目更多精彩內容:http://www.bianceng.cn/OS/unix/ * 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; }
出處:http://blog.csdn.net/muge0913/article/details/7518576