Linux/Unix系统编程手册-笔记26. 守护进程
Contents
守护进程指常驻后台,没有控制终端的进程。
创建守护进程
- 执行fork(), 父进程退出,子进程变成init的子进程继续运行,这步有两个原因:
- 假设守护进程是从命令行启动的,shell会注意到父进程的终止,并让子进程继续在后台运行。
- 能保证子进程不是一个进程组首进程,以保证接下来的步骤能正确执行。
- 子进程调用setsid(),开启一个新会话,和终端断开连接。
- 确保守护进程不要成为控制终端,有两种方法:
- 在可能open()一个终端设备时指定O_NOCTTY标志。
- 或者更简单的方法是在调用setsid()后再次调用fork(),这样子进程就不是一个会话首进程,也就不能成为控制终端。
- 清除进程的umask。
- 改变进程的当前工作目录,一般改成根目录
/
。 - 关闭所有从父进程继承来的文件描述符。守护进程也可以选择保留打开的文件描述符,但关闭文件描述符有很多理由,守护进程没有终端,所以文件描述符0,1,2对它来说没有用,守护进程常驻后台,我们无法卸载它持有打开的文件描述的文件系统分区。还有就是文件描述符是有限的资源。
- 关闭文件描述符0、1、2后,通常需要把这几个文件描述符指向到 /dev/null,为了保证守护进程调用的函数库中对这几个文件描述符执行I/O操作不会报错。
守护进程指南
- 关机时,init会给所有进程发送SIGTERM,默认会终止进程,建立了信号处理函数的进程可以在这时候执行快速的清理操作,因为5s之后会收到init发来的SIGKILL。在这5s中,所有进程都可以在信号处理函数中进行清理操作,所以CPU资源可能会十分紧张。
- 守护进程需要常驻后台,所以需要十分注意内存泄漏问题。
- 许多守护进程需要确保在同一时间只有一个实例在运行。
SIGHUP重初始化守护进程
- 守护进程长时间运行,一般是在它运行的时候读入配置文件,有的时候想要在它运行时更改配置。
- 守护进程会产生log文件,若它不关闭log文件,我们就没办法删除log文件,长此以往log会越来越大,需要一个方法告诉守护进程关闭log文件,打开一个新的log文件。
上述的解决方法就是建立SIGHUP的信号处理函数。之所以选这个信号,是因为SIGHUP是当和终端断开时通知控制进程的。守护进程没有终端,所以这个信号没啥用,可以借来用用。
用法就是在SIGHUP信号处理函数中设置一个flag,当守护进程中检测到falg被修改就重新读取配置文件,并重新打开一个新的。