守护进程
1. 什么是守护进程
守护进程(英语:daemon,/ˈdiːmən/或/ˈdeɪmən/)是一种在后台执行的序。此类程序会被以进程的形式初始化。
守护进程程序的名称通常以字母“d”结尾:例如,syslogd就是指管理系统日志的守护进程。mysqld 是数据库mysql的守护进程,mongod 是数据库mongo的守护进程。
2. 守护进程的实现
2.1 预备知识
(1) 会话 session
(2) 控制终端 controlling terminal
可以参考《Unix环境高级编程》9.5, 9.6
2.1 思考:守护进程有哪些特点
(1) 在后台运行
(2) 脱离控制终端控制
2.2 实现方案
实际实现就是围绕2.1 中两个特点的实现
(1) 起始进程调用fork,产生子进程,然后exit退出。这个步骤有两个目的:
A:如果父进程是shell命令运行,那么exit可以使shell认为启动程序命令执行完毕。(就是后台运行)
B:使子进程和父进程同一进程组,但不是进程组的首进程。为调用
(2) 子进程调用 setsid 创建一个新的对话(session)。这个步骤有以下目的:
A: 成为新对话期的首进程
B: 成为一个新进程组的首进程
C: 没有控制终端
(3) 儿子进程再次调用fork,然后儿子进程终止。目的:
防止儿子进程取得控制终端。因为对于SVR4系统,当对话首进程打开一个尚未与任何会话关联的终端设备时,此设备自动作为控制终端分配给该会话。
(4) 将当前工作目录改到根目录。因为进程工作时,它所在的工作目录是不能卸下的。
(5) 设置文件创建掩码为0。继承自父进程的掩码不一定适用于子进程。
(6) 关闭不需要的文件描述符。
2.3 具体实现方案
参考开源 web框架:lighttpd 的源码实现
(src/server.c 中的 daemonize函数)
下图是Lighttpd 1.4.20版本中的daemonize实现
对于关闭文件描述符,重定向标准输入、输出等,有的调用该函数之前完成,有的Lighttpd本身就不需要做。但是主要步骤都有了。