reboot系统调用及示例

我们来学习一下 reboot 这个系统调用。它是一个底层的 Linux 系统调用,用于重启、关闭或挂起你的计算机 。

1. 函数介绍

reboot 系统调用(System Call)提供了直接与 Linux 内核交互以控制机器状态(如重启、关机)的接口 。顾名思义,它的主要作用是重新启动机器,但根据提供的参数,它也能执行关闭电源、挂起系统等操作 。这与用户通常在命令行使用的 reboot 命令不同,后者是一个更高级别的程序,内部可能会调用这个系统调用 。

reboot系统调用及示例-CSDN博客

2. 函数原型

#include <unistd.h>
#include <linux/reboot.h> // 包含定义的常量

// 注意:实际的系统调用接口通常带有前缀下划线
int __reboot(int magic, int magic2, unsigned int cmd, void *arg);

注意:直接使用 __reboot 系统调用比较复杂且不推荐。通常,标准 C 库(glibc)会提供一个更方便的包装函数 reboot

更常用的 glibc 包装函数原型:

#include <sys/reboot.h> // glibc 封装函数的头文件

int reboot(int cmd);

3. 功能

这个系统调用的核心功能是根据 cmd 参数的值来执行不同的系统级操作,主要包括重启系统、关闭系统电源、挂起系统或启用/禁用 Ctrl+Alt+Del 组合键的功能 。

4. 参数

对于 glibc 封装的 reboot(int cmd) 函数:

  • cmdint 类型。这个参数指定了要执行的具体操作。常见的值定义在 sys/reboot.h 头文件中,例如:
    • LINUX_REBOOT_CMD_RESTART: 立即重启系统。
    • LINUX_REBOOT_CMD_HALT: 停止操作系统,但不关闭电源(挂起)。
    • LINUX_REBOOT_CMD_POWER_OFF: 停止操作系统并关闭电源(如果硬件支持)。
    • LINUX_REBOOT_CMD_RESTART2: 重启系统,并传递一个可选的命令行参数给内核(通过 arg 参数,但这在 glibc 包装函数中不直接暴露)。
    • LINUX_REBOOT_CMD_CAD_ON: 允许使用 Ctrl+Alt+Del 组合键重启系统。
    • LINUX_REBOOT_CMD_CAD_OFF: 禁止使用 Ctrl+Alt+Del 组合键。

对于底层的 __reboot(int magic, int magic2, unsigned int cmd, void *arg) 系统调用:

  • magicint 类型。第一个“魔数”,必须是 LINUX_REBOOT_MAGIC1 。这是为了防止意外调用系统调用 。
  • magic2int 类型。第二个“魔数”,必须是 LINUX_REBOOT_MAGIC2 或 LINUX_REBOOT_MAGIC2A/B/C 中的一个 。同样是为了防止误操作 。
  • cmdunsigned int 类型。指定要执行的操作,与 glibc reboot 的 cmd 参数类似,但可能使用内核空间定义的常量(如 LINUX_REBOOT_CMD_*)。
  • argvoid * 类型。一个指向缓冲区的指针,用于传递附加参数,例如传递给内核的命令行字符串(当 cmd 为 LINUX_REBOOT_CMD_RESTART2 时)。

5. 返回值

  • 成功: 对于 reboot(int cmd),如果调用成功,通常不会返回,因为系统会立即执行指定的操作(如重启或关机)。
  • 失败: 返回 -1,并设置全局变量 errno 来指示错误原因,最常见的失败原因是权限不足(需要 root 权限)。

6. 相似函数或关联函数

  • reboot 命令: 用户空间的标准命令行工具,用于重启系统,内部可能调用 reboot() 系统调用 。
  • shutdown 命令: 更通用的关机/重启命令,允许指定时间、广播消息等,最终也可能调用 reboot() 系统调用。
  • poweroff 命令: 用于关闭系统电源,通常也是通过系统调用实现。
  • halt 命令: 停止系统,行为取决于实现和参数,有时与 poweroff 类似。
  • sync 系统调用: 在执行 reboot 之前,通常会先调用 sync() 将所有未写入磁盘的数据刷新到磁盘,以防数据丢失。

7. 示例代码

注意: 运行此代码需要 root 权限,因为它执行的是特权操作。系统会立即重启,所以请确保保存所有工作。

#include <stdio.h>
#include <unistd.h> // 包含 sync
#include <sys/reboot.h> // 包含 reboot 函数和命令常量
#include <errno.h>
#include <string.h>

int main() {
    printf("准备重启系统...\n");

    // 1. 强烈建议在重启前先同步文件系统
    // 这会将所有缓存中的数据写入磁盘,防止数据丢失
    printf("正在同步文件系统...\n");
    sync(); // 执行同步操作
    // sync() 通常没有返回值用于检查错误,它尽力而为

    // 2. 调用 reboot 系统调用 (通过 glibc 包装)
    // 使用 LINUX_REBOOT_CMD_RESTART 命令重启系统
    printf("正在调用 reboot 系统调用...\n");
    if (reboot(LINUX_REBOOT_CMD_RESTART) == -1) {
        // 如果返回 -1,表示调用失败
        perror("reboot"); // 打印具体的错误原因
        fprintf(stderr, "错误: 无法重启系统。请确保以 root 权限运行此程序。\n");
        return 1; // 返回错误码
    }

    // 如果 reboot 调用成功,下面的代码通常不会被执行,
    // 因为系统已经开始重启过程。
    printf("系统调用已执行,但程序仍在运行?这很奇怪。\n");

    return 0; // 理论上不会到达这里
}

编译和运行:

# 假设代码保存在 reboot_example.c 中
# 编译
gcc -o reboot_example reboot_example.c

# 运行 (需要 root 权限)
sudo ./reboot_example

再次提醒: 执行此程序会使您的计算机立即重启,请谨慎操作!

此条目发表在linux文章分类目录。将固定链接加入收藏夹。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注