在 Linux 下用 C/C++ 写守护进程(Daemon),核心是把进程“脱离终端、后台运行”。下面从原理 → 标准写法 → 示例代码 → 进阶建议一步步说明。
一个标准守护进程通常要做这几件事:
/dev/null#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdlib>
void daemonize() {
pid_t pid = fork();
if (pid < 0) exit(1);
if (pid > 0) exit(0); // 父进程退出
setsid(); // 创建新会话
pid = fork();
if (pid < 0) exit(1);
if (pid > 0) exit(0); // 再次 fork,防止重新打开终端
chdir("/"); // 切换根目录
umask(0); // 重置 umask
// 重定向标准输入输出
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 (true) {
// 守护进程逻辑
sleep(10);
}
return 0;
}
编译运行:
g++ daemon.cpp -o daemon
./daemon
ps -ef | grep daemon
daemon()#include <unistd.h>
int main() {
if (daemon(0, 0) < 0) {
return 1;
}
while (true) {
sleep(10);
}
}
参数说明:
daemon(0, 0)
0:不 chdir 到 /0:不重定向到 /dev/null⚠️ 注意:daemon() 在部分嵌入式系统中可能不可用。
不要自己写守护进程逻辑,让系统管理:
# /etc/systemd/system/mydaemon.service
[Unit]
Description=My Daemon
[Service]
ExecStart=/usr/bin/mydaemon
Restart=always
[Install]
WantedBy=multi-user.target
systemctl start mydaemon
systemctl enable mydaemon
✅ 优点:
程序里只做最小 fork,剩下的交给 systemd。
守护进程不能使用终端,推荐:
syslog示例(syslog):
#include <syslog.h>
openlog("mydaemon", LOG_PID, LOG_DAEMON);
syslog(LOG_INFO, "daemon started");
❌ 忘记 setsid → 仍是终端子进程
❌ 没重定向 stdout → 程序卡死
❌ 在挂载目录中运行 → 无法 umount
❌ 用 while(1) 不处理信号 → 无法优雅退出
你打算用在什么场景?(服务?工具?嵌入式?)