**守护进程(Daemon)** 是一种在后台运行的特殊进程
在 Unix/Linux 系统中,守护进程(Daemon) 是一种在后台运行的特殊进程,它独立于控制终端,通常用户登录/注销的影响,通常用于提供持续的系统服务(如 Web 服务器、数据库服务等)。
守护进程的核心特点
- 后台运行:脱离终端控制,在后台持续执行。
- 独立于终端:不与任何终端关联,即使启动它的终端关闭,进程仍继续运行。
- 生命周期长:通常在系统启动时开始运行,直到系统关闭才终止。
- 无用户交互:运行过程中不需要用户输入,通过配置文件或信号进行管理。
- 父进程为 init 或 systemd:启动后会与父进程脱离,由系统初始化进程(如
init
、systemd
)接管。
守护进程的典型应用
- 网络服务:如
nginx
(Web 服务器)、sshd
(SSH 服务)。 - 系统服务:如
crond
(定时任务服务)、syslogd
(日志服务)。 - 后台处理:如数据库服务(
mysqld
)、文件索引服务等。
如何创建守护进程(编程角度)
创建守护进程需要遵循特定的步骤(称为"守护化"),核心是脱离终端并建立新的进程环境:
-
创建子进程,父进程退出
父进程退出后,子进程成为孤儿进程,由init
进程接管,脱离终端控制。 -
子进程创建新会话(setsid())
调用setsid()
使子进程成为新会话的首领,彻底脱离原终端。 -
改变当前工作目录(chdir())
通常切换到根目录(/
),避免占用可卸载的文件系统。 -
重设文件权限掩码(umask())
清除权限掩码,确保创建文件时拥有预期的权限。 -
关闭不需要的文件描述符
关闭标准输入(stdin
)、标准输出(stdout
)、标准错误(stderr
),避免与终端产生关联。
简单示例代码
#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/nullopen("/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
结尾,如sshd
、httpd
)。 - 启动:系统服务通常通过
systemctl start 服务名
启动。 - 停止:通过
systemctl stop 服务名
或发送信号(如kill -TERM 进程ID
)。 - 日志:守护进程的输出通常写入日志文件(如
/var/log/
目录下),而非终端。
守护进程是 Linux 系统中提供长期服务的基础,其设计确保了服务的稳定性和独立性。