一) 什么是守护进程?
守护进程(Daemon) 是一种在后台运行的特殊进程,通常在系统启动时自动启动,并在整个系统运行期间一直运行,直到系统关闭。它们通常用于提供系统服务,如网络、日志记录、计划任务等。“守护进程”这个概念由麻省理工学院MAC项目的程序员发明。费南多·柯巴托于1963年在MAC项目任务。根据他的说法,他的团队最早采用daemon这个概念,其灵感来源于麦克斯韦妖——一种物理学和热力学中虚构的介质,能帮助排列分子。他对此表示:“我们别出心裁地开始使用daemon这个词来描述后台进程,它们不知疲倦地处理系统中的杂务。” Unix系统继承了这个术语。作为一种在后台起作用的超自然存在,麦克斯韦妖与古希腊神话中的代蒙一致。
通常来讲,daemon是单词“demon”较早的拼写形式,源于希腊语δαίμων。伊维·尼梅斯在Unix系统管理手册中对守护进程有如下阐释:
许多人将“daemon”与“demon”这两个词等同,借此暗示UNIX与阴间的某种邪恶联系。这是一种极坏的误解。“Daemon”事实上是“demon”另一种早得多的写法;daemon并无善或恶的倾向,相反,它定义一个人的质量或性格。古希腊的“个人代蒙”概念类似于现代的“守护神”概念——快乐即是得到友好灵魂帮助或保护的状态。通常地,UNIX系统看起来充斥着守护神和恶鬼。
守护进程特点:
- 无终端(不与任何用户终端直接关联)
- 后台运行(不会与用户交互)
- 通常由
init
或systemd
启动 - 持续运行(不会随用户登录/退出而停止)
- 周期性执行某种任务或等待某些发生的事件。
二) 常见的守护进程
2.1) 系统相关
守护进程 | 作用 |
---|---|
systemd |
现代 Linux 的服务管理器,取代 init |
init |
传统的 Linux 初始化进程,管理系统启动 |
udevd |
设备管理守护进程,负责 /dev 设备文件 |
syslogd |
负责系统日志记录 |
2.2) 网络服务
守护进程 | 作用 |
---|---|
sshd |
提供 SSH 远程登录服务 |
httpd |
提供 Web 服务(Apache/Nginx) |
ftpd |
提供 FTP 文件传输服务 |
named |
提供 DNS 解析服务 |
dhcpd |
提供 DHCP 服务 |
2.3) 任务调度
守护进程 | 作用 |
---|---|
cron |
计划任务调度服务 |
atd |
处理一次性定时任务 |
另外还有被动守护进程(由xinetd启动):telnet、finger、ktalk等
三) 守护进程的工作方式
四)如何创建守护进程?
守护进程通常由系统自动启动,但也可以手动创建。
4.1) 使用 nohup
& &
(简单方式)
nohup
允许进程不受终端退出影响,并继续运行:
nohup ./my_script.sh > output.log 2>&1 &
4.2) 使用 systemd
创建守护进程
systemd
是现代 Linux 系统的服务管理工具,可以用来管理守护进程。
步骤 1:创建 mydaemon.service
sudo nano /etc/systemd/system/mydaemon.service
内容:
[Unit] Description=My Custom Daemon After=network.target [Service] ExecStart=/usr/local/bin/mydaemon Restart=always User=root [Install] WantedBy=multi-user.target
步骤 2:启动守护进程
sudo systemctl daemon-reload # 重新加载 systemd 配置 sudo systemctl start mydaemon # 启动进程 sudo systemctl enable mydaemon # 设置开机自启
步骤 3:检查状态
sudo systemctl status mydaemon
五) 编写 C 语言守护进程

实现步骤:
示例代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <signal.h> void daemonize() { pid_t pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); // 终止父进程 } // 创建新会话 if (setsid() < 0) { exit(EXIT_FAILURE); } // 捕获信号 signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); pid = fork(); // 再次 fork,确保进程不会获得终端控制 if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0); // 允许进程创建任何权限的文件 chdir("/"); // 改变工作目录,避免锁定文件系统 // 关闭标准输入、输出、错误 int fd = open("/dev/null", O_RDWR); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); close(fd); } int main() { daemonize(); while (1) { sleep(10); // 模拟后台任务 } return 0; }
编译运行:
gcc mydaemon.c -o mydaemon ./mydaemon &
六) 如何管理守护进程?
6.1) 查看守护进程
ps aux | grep daemon pgrep -l daemon
6.2) 终止守护进程
pkill mydaemon kill -9 PID
6.3) 重新加载守护进程
systemctl restart mydaemon
6.4) 监控守护进程
使用 ps
命令
ps aux | grep mydaemon
使用 pgrep
查找进程
pgrep -l mydaemon
使用 systemctl
查看状态
systemctl status mydaemon
七)守护进程生命周期
守护进程一般具有长期运行的特性,并且遵循以下生命周期:
阶段 | 说明 |
---|---|
创建 | 由 init 、systemd 或手动启动 |
初始化 | 进行 fork() 、setsid() 、更改目录、重定向输入输出 |
运行 | 在后台循环执行任务,如监听端口、处理请求 |
重启 | 部分守护进程可以通过 SIGHUP 信号重新加载配置 |
终止 | 进程可以被 kill 或 systemctl stop 终止 |
八)信号处理
守护进程通常通过信号(Signal) 来处理不同的事件:
信号 | 作用 |
---|---|
SIGHUP |
重新加载配置 |
SIGTERM |
终止进程 |
SIGKILL |
强制杀死进程 |
SIGUSR1 |
自定义操作 |
示例:
kill -SIGHUP <PID> # 让守护进程重新加载配置
九) 守护进程 vs. 普通进程
特性 | 守护进程 | 普通进程 |
---|---|---|
运行方式 | 后台 | 前台 |
终端绑定 | 无终端 | 绑定终端 |
是否受用户退出影响 | 否 | 是 |
作用 | 提供长期服务 | 执行一次性任务 |
十) 结论
- 守护进程是 Linux 系统的重要组成部分,用于提供持续运行的服务,如日志、网络、任务调度等。
- 可以通过
nohup
、systemd
或fork()
创建守护进程。 - 使用
systemd
是现代 Linux 管理守护进程的推荐方式。 - 编写守护进程需要注意
fork()
、setsid()
、chdir()
、信号处理等关键步骤。