对于Unix/linux编程,最好的工具应该是man了,我们看一下man究竟可以可以干什么。
man man 一下看看,手册用数字分成了9部分,我想学习编程的时候应该会经常用到2和3吧
1 可执行程序或 shell 命令
2 系统调用(内核提供的函数)
3 库调用(程序库中的函数)
4 特殊文件(通常位于 /dev)
5 文件格式和规范,如 /etc/passwd
6 游戏
7 杂项(包括宏包和规范,如 man(7), groff(7))
8 系统管理命令(通常只针对 root 用户)
9 内核例程 [非标准]
小节名称通常包括 NAME, 概述(SYNOPSIS), 配置(CONFIGURATION),
描述(DESCRIPTION), 选项(OPTIONS), 退出状态(EXIT STATUS),
返回值(RETURN VALUE), 错误(ERRORS), 环境(ENVIRONMENT), 文件(FILES),
版本(VERSIONS), 符合标准(CONFORMING TO), 注(NOTES), 缺陷(BUGS),
示例(EXAMPLE), 作者(AUTHORS), 和 亦见(SEE ALSO).
接着我们来看一下 reboot这个系统调用 man 2 reboot
SYNOPSIS
/* For libc4 and libc5 the library call and the system call
are identical, and since kernel version 2.1.30 there are
symbolic names LINUX_REBOOT_* for the constants and a
fourth argument to the call: */
#include <unistd.h>
#include <linux/reboot.h>
int reboot(int magic, int magic2, int cmd, void *arg);
/* Under glibc some of the constants involved have gotten
symbolic names RB_*, and the library call is a 1-argument
wrapper around the 3-argument system call: */
#include <unistd.h>
#include <sys/reboot.h>
int reboot(int cmd);
从注释上我们看出4个参数的reboot是系统调用,1个参数的reboot是封装过的库函数。
DESCRIPTION
The reboot() call reboots the system, or enables/disables the reboot
keystroke (abbreviated CAD, since the default is Ctrl-Alt-Delete; it
can be changed using loadkeys(1)).
//这里说明了reboot函数的功能重启和打开/关闭 CAD
This system call will fail (with EINVAL) unless magic equals
LINUX_REBOOT_MAGIC1 (that is, 0xfee1dead) and magic2 equals
LINUX_REBOOT_MAGIC2 (that is, 672274793). However, since 2.1.17 also
LINUX_REBOOT_MAGIC2A (that is, 85072278) and since 2.1.97 also
LINUX_REBOOT_MAGIC2B (that is, 369367448) and since 2.5.71 also
LINUX_REBOOT_MAGIC2C (that is, 537993216) are permitted as value for
magic2. (The hexadecimal values of these constants are meaningful.)
The cmd argument can have the following values:
672274793 = 0x28121969
85072278 = 0x05121996
369367448 = 0x16041998
537993216 = 0x20112000
这里将这些看似随机的魔数转化成16进制能看的出是一些日期,百度一下就发现了这个linus本人和三个女儿的生日
/
-
LINUX_REBOOT_CMD_CAD_OFF
- (RB_DISABLE_CAD, 0). CAD is disabled. This means that the CAD keystroke will cause a SIGINT signal to be sent to init (process 1), whereupon this process may decide upon a proper action (maybe: kill all processes, sync, reboot). LINUX_REBOOT_CMD_CAD_ON
- (RB_ENABLE_CAD, 0x89abcdef). CAD is enabled. This means that the CAD keystroke will immediately cause the action associated with LINUX_REBOOT_CMD_RESTART. LINUX_REBOOT_CMD_HALT
- (RB_HALT_SYSTEM, 0xcdef0123; since 1.1.76). The message "System halted." is printed, and the system is halted. Control is given to the ROM monitor, if there is one. If not preceded by a sync(2), data will be lost. LINUX_REBOOT_CMD_KEXEC (since Linux 2.6.13)
- Execute a kernel that has been loaded earlier with kexec_load(2). This option is only available if the kernel was configured with CONFIG_KEXEC. LINUX_REBOOT_CMD_POWER_OFF
- (0x4321fedc; since 2.1.30). The message "Power down." is printed, the system is stopped, and all power is removed from the system, if possible. If not preceded by a sync(2), data will be lost. LINUX_REBOOT_CMD_RESTART
- (RB_AUTOBOOT, 0x1234567). The message "Restarting system." is printed, and a default restart is performed immediately. If not preceded by a sync(2), data will be lost. LINUX_REBOOT_CMD_RESTART2
- (0xa1b2c3d4; since 2.1.30). The message "Restarting system with command aq%saq" is printed, and a restart (using the command string given in arg) is performed immediately. If not preceded by a sync(2), data will be lost.
Only the superuser may call reboot().
The precise effect of the above actions depends on the architecture. For the i386 architecture, the additional argument does not do anything at present (2.1.122), but the type of reboot can be determined by kernel command-line arguments ("reboot=...") to be either warm or cold, and either hard or through the BIOS.
//这里讲了一下cmd参数的作用 重启、关机、开关CAD.
然后,我们欣赏一下 sys_reboot系统调用是如何实现的.
896 asmlinkage long sys_reboot(int magic1,
int magic2, unsigned int cmd, void __user * arg)
897 {
898 char buffer[256];
899
900 /* We only trust the superuser with rebooting the system. */
901 if (!capable(CAP_SYS_BOOT))
902 return -EPERM;
903
904 /* For safety, we require "magic" arguments. */
905 if (magic1 != LINUX_REBOOT_MAGIC1 ||
906 (magic2 != LINUX_REBOOT_MAGIC2 &&
907 magic2 != LINUX_REBOOT_MAGIC2A &&
908 magic2 != LINUX_REBOOT_MAGIC2B &&
909 magic2 != LINUX_REBOOT_MAGIC2C))
910 return -EINVAL;
911
912 /* Instead of trying to make the power_off code look like
913 * halt when pm_power_off is not set do it the easy way.
914 */
915 if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
916 cmd = LINUX_REBOOT_CMD_HALT;
917
918 lock_kernel();
919 switch (cmd) {
920 case LINUX_REBOOT_CMD_RESTART:
921 kernel_restart(NULL);
922 break;
923
924 case LINUX_REBOOT_CMD_CAD_ON:
925 C_A_D = 1;
926 break;
927
928 case LINUX_REBOOT_CMD_CAD_OFF:
929 C_A_D = 0;
930 break;
931
932 case LINUX_REBOOT_CMD_HALT:
933 kernel_halt();
934 unlock_kernel();
935 do_exit(0);
936 break;
937
938 case LINUX_REBOOT_CMD_POWER_OFF:
939 kernel_power_off();
940 unlock_kernel();
941 do_exit(0);
942 break;
943
944 case LINUX_REBOOT_CMD_RESTART2:
945 if (strncpy_from_user(&buffer[0], arg,
sizeof(buffer) - 1) < 0) {
946 unlock_kernel();
947 return -EFAULT;
948 }
949 buffer[sizeof(buffer) - 1] = '\0';
950
951 kernel_restart(buffer);
952 break;
953
954 case LINUX_REBOOT_CMD_KEXEC:
955 kernel_kexec();
956 unlock_kernel();
957 return -EINVAL;
958
959 #ifdef CONFIG_HIBERNATION
960 case LINUX_REBOOT_CMD_SW_SUSPEND:
961 {
962 int ret = hibernate();
963 unlock_kernel();
964 return ret;
965 }
966 #endif
967
968 default:
969 unlock_kernel();
970 return -EINVAL;
971 }
972 unlock_kernel();
973 return 0;
974 }