温馨提示×

C++ Linux系统如何编写守护进程

小樊
61
2025-08-14 03:13:33
栏目: 编程语言

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

  1. 创建子进程并退出父进程:守护进程必须是后台运行的,因此需要从父进程中分离子进程。

  2. 创建新的会话:使用setsid()函数创建一个新的会话,使守护进程成为新会话的领头进程,并脱离控制终端。

  3. 设置文件权限掩码:使用umask(0)将文件权限掩码设置为0,防止守护进程创建的文件继承父进程的权限。

  4. 切换工作目录:将工作目录切换到根目录(/),以防止占用可卸载的文件系统。

  5. 关闭标准文件描述符:关闭标准输入、输出和错误流,重定向它们到/dev/null,因为守护进程不需要与终端交互。

  6. 处理信号:设置适当的信号处理程序,以便在接收到特定信号时能够优雅地终止或重新启动。

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

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

void daemonize() {
    pid_t pid;

    // Fork off the parent process
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }
    if (pid > 0) {
        // Exit first parent
        exit(EXIT_SUCCESS);
    }

    // Create a new session
    if (setsid() < 0) {
        exit(EXIT_FAILURE);
    }

    // Ignore SIGHUP signal
    signal(SIGHUP, SIG_IGN);

    // Fork off the second parent process
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }
    if (pid > 0) {
        // Exit from second parent
        exit(EXIT_SUCCESS);
    }

    // Set file permissions mask
    umask(0);

    // Change the current working directory to root
    if (chdir("/") < 0) {
        exit(EXIT_FAILURE);
    }

    // Close standard file descriptors
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    // Redirect standard file descriptors to /dev/null
    open("/dev/null", O_RDONLY); // stdin
    open("/dev/null", O_RDWR);   // stdout
    open("/dev/null", O_RDWR);   // stderr
}

void signalHandler(int signum) {
    std::cout << "Received signal " << signum << std::endl;
    // Perform cleanup or restart logic here
    exit(signum);
}

int main() {
    // Daemonize the process
    daemonize();

    // Set up signal handler
    signal(SIGHUP, signalHandler);
    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    // Main loop
    while (true) {
        // Perform daemon tasks
        sleep(1);
    }

    return 0;
}

解释

  1. fork off the parent process:第一次fork()创建子进程,父进程退出。
  2. Create a new sessionsetsid()创建新的会话,使子进程成为领头进程。
  3. Ignore SIGHUP signal:忽略SIGHUP信号,防止守护进程在终端关闭后重新启动。
  4. Fork off the second parent process:第二次fork()确保守护进程不是会话领头进程的子进程。
  5. Set file permissions maskumask(0)设置文件权限掩码为0。
  6. Change the current working directory to rootchdir("/")将工作目录切换到根目录。
  7. Close standard file descriptors:关闭标准输入、输出和错误流。
  8. Redirect standard file descriptors to /dev/null:将标准输入、输出和错误流重定向到/dev/null
  9. Set up signal handler:设置信号处理程序,处理SIGHUPSIGINTSIGTERM信号。
  10. Main loop:守护进程的主循环,执行守护任务。

这个示例展示了如何编写一个基本的守护进程。根据具体需求,你可能需要添加更多的功能和错误处理逻辑。

0