linux

如何用C++编写Linux下的守护进程

小樊
45
2025-09-03 05:34:21
栏目: 编程语言

在Linux下编写一个守护进程(Daemon)通常涉及以下几个步骤:

  1. 创建子进程:通过fork()创建一个子进程,父进程退出,使子进程成为孤儿进程,由init进程接管。
  2. 创建新会话:使用setsid()创建一个新的会话,使子进程成为新会话的领头进程,脱离控制终端。
  3. 设置工作目录:将工作目录切换到根目录(/),避免占用可卸载的文件系统。
  4. 重设文件权限掩码:使用umask(0),确保守护进程拥有最大的权限。
  5. 关闭不必要的文件描述符:关闭标准输入、输出和错误流,并关闭其他不必要的文件描述符。
  6. 处理信号:注册信号处理器,以优雅地处理终止信号等。

下面是一个简单的C++示例,演示如何创建一个基本的守护进程:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <cstring>

// 信号处理函数
volatile sig_atomic_t stop;

void handle_signal(int signum) {
    stop = signum;
}

int main() {
    // 第一步:fork子进程
    pid_t pid = fork();
    if (pid > 0) {
        // 父进程退出
        exit(0);
    }
    if (pid < 0) {
        // 错误处理
        std::cerr << "Fork failed!" << std::endl;
        return 1;
    }

    // 第二步:创建新会话
    if (setsid() < 0) {
        std::cerr << "Setsid failed!" << std::endl;
        return 1;
    }

    // 第三步:设置工作目录
    if (chdir("/") < 0) {
        std::cerr << "Chdir failed!" << std::endl;
        return 1;
    }

    // 第四步:重设文件权限掩码
    umask(0);

    // 第五步:关闭文件描述符
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    // 可选:重定向标准文件描述符到/dev/null
    open("/dev/null", O_RDONLY); // stdin
    open("/dev/null", O_RDWR);   // stdout
    open("/dev/null", O_RDWR);   // stderr

    // 第六步:注册信号处理器
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handle_signal;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);

    // 守护进程主循环
    while (!stop) {
        // 执行守护进程的任务
        // 例如:日志记录、监控、定时任务等

        sleep(10); // 每10秒检查一次信号
    }

    std::cout << "Daemon stopped." << std::endl;
    return 0;
}

解释

  1. Fork子进程:通过fork()创建子进程,父进程退出,使子进程成为孤儿进程,由init进程接管。
  2. 创建新会话:使用setsid()创建一个新的会话,使子进程成为新会话的领头进程,脱离控制终端。
  3. 设置工作目录:将工作目录切换到根目录(/),避免占用可卸载的文件系统。
  4. 重设文件权限掩码:使用umask(0),确保守护进程拥有最大的权限。
  5. 关闭文件描述符:关闭标准输入、输出和错误流,并关闭其他不必要的文件描述符。可选地,可以将标准文件描述符重定向到/dev/null
  6. 注册信号处理器:注册信号处理器,以优雅地处理终止信号等。

编译和运行

保存上述代码到一个文件,例如daemon.cpp,然后使用以下命令编译和运行:

g++ -o daemon daemon.cpp
./daemon

注意事项

通过以上步骤,你可以创建一个基本的守护进程。根据具体需求,可以进一步扩展和优化。

0
看了该问题的人还看了