**守护进程(Daemon)** 是一种在后台运行的特殊进程

在 Unix/Linux 系统中,守护进程(Daemon) 是一种在后台运行的特殊进程,它独立于控制终端,通常用户登录/注销的影响,通常用于提供持续的系统服务(如 Web 服务器、数据库服务等)。

守护进程的核心特点

  1. 后台运行:脱离终端控制,在后台持续执行。
  2. 独立于终端:不与任何终端关联,即使启动它的终端关闭,进程仍继续运行。
  3. 生命周期长:通常在系统启动时开始运行,直到系统关闭才终止。
  4. 无用户交互:运行过程中不需要用户输入,通过配置文件或信号进行管理。
  5. 父进程为 init 或 systemd :启动后会与父进程脱离,由系统初始化进程(如 initsystemd)接管。

守护进程的典型应用

  • 网络服务:如 nginx(Web 服务器)、sshd(SSH 服务)。
  • 系统服务:如 crond(定时任务服务)、syslogd(日志服务)。
  • 后台处理:如数据库服务(mysqld)、文件索引服务等。

如何创建守护进程(编程角度)

创建守护进程需要遵循特定的步骤(称为"守护化"),核心是脱离终端并建立新的进程环境:

  1. 创建子进程,父进程退出

    父进程退出后,子进程成为孤儿进程,由 init 进程接管,脱离终端控制。

  2. 子进程创建新会话(setsid())

    调用 setsid() 使子进程成为新会话的首领,彻底脱离原终端。

  3. 改变当前工作目录(chdir())

    通常切换到根目录(/),避免占用可卸载的文件系统。

  4. 重设文件权限掩码(umask())

    清除权限掩码,确保创建文件时拥有预期的权限。

  5. 关闭不需要的文件描述符

    关闭标准输入(stdin)、标准输出(stdout)、标准错误(stderr),避免与终端产生关联。

简单示例代码

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

void create_daemon() {
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    }
    if (pid > 0) {  // 父进程退出
        exit(0);
    }

    // 子进程创建新会话
    if (setsid() < 0) {
        perror("setsid failed");
        exit(1);
    }

    // 再次 fork 避免子进程成为会话首领(可选,增强安全性)
    pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    }
    if (pid > 0) {
        exit(0);
    }

    // 改变工作目录到根目录
    chdir("/");

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

    // 关闭所有打开的文件描述符
    for (int fd = sysconf(_SC_OPEN_MAX); fd >= 0; fd--) {
        close(fd);
    }

    // 重定向标准输入/输出/错误到/dev/null
    open("/dev/null", O_RDWR);  // stdin (0)
    dup(0);                     // stdout (1)
    dup(0);                     // stderr (2)
}

int main() {
    create_daemon();

    // 守护进程核心逻辑(此处示例为无限循环)
    while (1) {
        sleep(1);  // 模拟持续运行的服务
    }

    return 0;
}

如何管理守护进程

  • 查看 :通过 ps -ef | grep 进程名 查看(通常名称以 d 结尾,如 sshdhttpd)。
  • 启动 :系统服务通常通过 systemctl start 服务名 启动。
  • 停止 :通过 systemctl stop 服务名 或发送信号(如 kill -TERM 进程ID)。
  • 日志 :守护进程的输出通常写入日志文件(如 /var/log/ 目录下),而非终端。

守护进程是 Linux 系统中提供长期服务的基础,其设计确保了服务的稳定性和独立性。