【Linux】【守护进程】总结整理
守护进程(Daemon)是运行在后台的进程,通常没有与之关联的控制终端。守护进程在启动后会脱离控制终端,并继续在后台运行,即使用户退出登录或者终端关闭也不会影响它们的运行。守护进程常用于提供网络服务、定期执行任务或监控系统状态等。
守护进程的特点
- 无控制终端:守护进程没有控制终端,这意味着它们通常不能接收来自终端的输入或输出。
- 运行在后台:守护进程在后台运行,即使用户退出登录或关闭终端,守护进程仍然持续运行。
- 长期运行:守护进程通常设计为长期运行,直到手动停止或系统重启。
- 自动重启:有些守护进程会在意外终止后自动重启,以确保服务的连续性。
创建守护进程的步骤
创建守护进程通常涉及以下步骤:
- 创建子进程:使用
fork()
创建一个子进程。 - 成为会话领导者:在子进程中调用
setsid()
函数,使子进程成为一个新的会话的领导者,并与控制终端脱离。 - 改变当前工作目录:通常将当前工作目录更改为根目录
/
,以避免由于当前目录被卸载而导致的问题。 - 重设文件权限掩码:通常使用
umask(0)
设置文件权限掩码,这样守护进程创建的文件具有最宽松的权限。 - 关闭标准文件描述符:关闭标准输入、输出和错误文件描述符(通常是0、1和2),以防止这些描述符引用到已关闭的终端设备。
- 可能的第二次fork:为了确保守护进程不会保留任何进程组ID,有时会再次调用
fork()
,并在父进程中exit()
,这样可以确保子进程不会成为一个作业控制进程。
示例代码
以下是一个简单的守护进程创建示例,使用 C 语言编写:
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <sys/types.h>
5#include <fcntl.h>
6#include <signal.h>
7#include <sys/stat.h>
8#include <errno.h>
9
10void become_daemon() {
11 pid_t pid;
12 int i;
13
14 // 第一次fork
15 pid = fork();
16 if (pid < 0) {
17 fprintf(stderr, "fork #1 failed: %d (%s)\n", errno, strerror(errno));
18 exit(EXIT_FAILURE);
19 }
20 if (pid > 0) {
21 // 父进程退出
22 exit(EXIT_SUCCESS);
23 }
24
25 // 成为会话领导者
26 if (setsid() < 0) {
27 fprintf(stderr, "setsid failed: %d (%s)\n", errno, strerror(errno));
28 exit(EXIT_FAILURE);
29 }
30
31 // 第二次fork
32 pid = fork();
33 if (pid < 0) {
34 fprintf(stderr, "fork #2 failed: %d (%s)\n", errno, strerror(errno));
35 exit(EXIT_FAILURE);
36 }
37 if (pid > 0) {
38 // 父进程退出
39 exit(EXIT_SUCCESS);
40 }
41
42 // 改变当前工作目录
43 if ((chdir("/")) < 0) {
44 fprintf(stderr, "chdir failed: %d (%s)\n", errno, strerror(errno));
45 exit(EXIT_FAILURE);
46 }
47
48 // 重设文件权限掩码
49 umask(0);
50
51 // 关闭标准文件描述符
52 for (i = 0; i < 3; i++) {
53 close(i);
54 }
55
56 // 打开/dev/null作为新的标准文件描述符
57 open("/dev/null", O_RDWR);
58 dup2(0, 1);
59 dup2(0, 2);
60}
61
62int main() {
63 become_daemon();
64
65 // 守护进程的主要逻辑
66 while (1) {
67 printf("守护进程正在运行...\n");
68 sleep(5);
69 }
70
71 return 0;
72}
注意事项
- 守护进程应该能够处理信号,特别是
SIGTERM
和SIGHUP
信号。SIGTERM
通常用于请求守护进程优雅地终止,而SIGHUP
通常用于通知守护进程重新加载配置文件。 - 如果守护进程需要记录日志,通常会将日志写入到一个文件中,而不是标准输出。
- 守护进程通常需要通过命令行参数或配置文件来接受配置选项。
- 在某些情况下,守护进程还需要处理
SIGCHLD
信号,以确保子进程的资源被正确清理。 - 守护进程应该具有良好的错误处理机制,确保即使在遇到问题时也能稳定运行。
守护进程是操作系统中一个重要的组件,用于提供后台服务和支持功能。理解和掌握如何创建和管理守护进程对于开发系统服务和工具非常重要。