温馨提示×

Linux守护进程如何创建

小樊
47
2026-07-21 20:17:48
栏目: 智能运维

在 Linux 中,守护进程(Daemon)是一种在后台运行、不与终端关联的进程。创建守护进程有一套经典流程,下面从原理示例代码两方面说明。


一、守护进程的特点

  1. 后台运行,没有控制终端
  2. 父进程通常是 init(或 systemd
  3. 会话和进程组独立
  4. 工作目录通常设为 /
  5. 文件描述符关闭或重定向(stdin/stdout/stderr)
  6. 使用 fork() 脱离终端

二、创建守护进程的标准步骤(SysV 风格)

✅ 步骤概览

  1. fork() 一次,父进程退出
  2. 调用 setsid() 创建新会话
  3. fork() 第二次(可选,避免重新获得终端)
  4. 改变工作目录 chdir("/")
  5. 重设文件权限掩码 umask(0)
  6. 关闭或重定向标准文件描述符

三、C 语言示例(经典方式)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void create_daemon(void)
{
    pid_t pid;

    // 1. fork,父进程退出
    pid = fork();
    if (pid < 0) exit(1);
    if (pid > 0) exit(0);

    // 2. 创建新会话
    if (setsid() < 0) exit(1);

    // 3. 再 fork 一次(可选)
    pid = fork();
    if (pid < 0) exit(1);
    if (pid > 0) exit(0);

    // 4. 改变工作目录
    chdir("/");

    // 5. 重设文件权限掩码
    umask(0);

    // 6. 关闭标准输入输出
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    // 重定向到 /dev/null
    open("/dev/null", O_RDONLY); // stdin
    open("/dev/null", O_WRONLY); // stdout
    open("/dev/null", O_WRONLY); // stderr
}

int main(void)
{
    create_daemon();

    // 守护进程主体
    while (1) {
        sleep(10);
    }

    return 0;
}

四、为什么需要两次 fork()

fork 次数 作用
第一次 脱离父进程和终端
setsid() 成为会话首进程
第二次 防止重新打开控制终端

第二次 fork 不是必须的,但更安全。


五、现代 Linux 的推荐方式(systemd)

现在不推荐手写守护进程,而是由 systemd 管理。

示例 service 文件

[Unit]
Description=My Daemon

[Service]
ExecStart=/usr/local/bin/mydaemon
Restart=always

[Install]
WantedBy=multi-user.target

然后:

systemctl daemon-reload
systemctl start mydaemon
systemctl enable mydaemon

✅ systemd 自动完成:

  • 脱离终端
  • 日志管理(journald)
  • 自动重启
  • 权限控制

六、常见注意事项

  • 不要printf(stderr, ...)
  • ✅ 日志写入 syslog/var/log
  • ✅ 使用 kill(pid, SIGTERM) 控制退出

七、总结

场景 建议
学习 / 面试 手写 fork + setsid
生产环境 使用 systemd
简单后台 nohup ./app &

如果你需要 Python / Shell / systemd 实战示例,或想了解 如何优雅退出守护进程,可以继续问我。

0