原文:https://www.jianshu.com/p/fbe51e1147af
守护进程
守护进程daemon是一种生存周期很长的进程。它们通常在系统引导时启动,在系统关闭时终止。守护进程是没有终端的,它们一直在后台运行。
守护进程的特征
在Linux系统中,可以通过命令 ps -efj 来查看守护进程。例如下图:
从上图中可以看到 TTY 一列,该列显示每个进程的终端,对于问号(?)显示的进程,表明该进程没有控制终端。而CMD列中方括号[ ]显示的进程表明这是一个内核守护进程,对于用户守护进程则没有方括号[ ]。
编程规则
如果需要编写进程守护程序,则需要遵循一些基本规则,具体如下:
- 调用umask将文件模式创建屏蔽字设置为一个指定值。因为守护进程如果要创建文件,那么该文件必须指定权限,确保文件权限是自己期望的。
- 调用fork,然后使父进程exit,这是使得守护进程不关联终端的前提条件。另外,如果守护进程从终端命令行启动,那么父进程exit会使得shell认为该命令执行完毕从而正常返回。
- 调用setsid创建新会话,并丢掉控制终端。
- 将进程当前工作目录更改为根目录,因为进程可能启用于一个临时挂载的目录,如果进程一直执行,那么挂载目录就无法卸载。
5.关闭不再需要的文件描述符,主要防止守护进程误写。 - 打开/dev/null 文件,使得进程具有文件描述符0,1,2,这样做是为了预防守护进程调用的第三方接口或者库组件尝试从标准输入输出读写。
以上6点基本上是编写一个守护进程所必须的,也就是说,如果要编写一个严谨的守护进程,那么最好将上述步骤全部囊括。
出错记录
守护进程需要处理的一个问题是如何处理出错问题,因为守护进程没有控制终端,所以它无法进行标准错误输出,另外也不能简单地直接将出错信息写入到一个日志文件中,因为对管理人员而言,他不可能去统计记住系统中所有进程对应的出错记录日志文件(目录及其文件名)。因此需要有一个集中的出错记录管理守护进程来专门统一负责出错记录。
对于内核守护进程,可以通过调用log( )函数来向出错日志统计守护进程发送消息,但我们不会编写内核级守护进程。
对于用户守护进程,可以通过调用syslog( )函数来向出错日志统计守护进程发送消息,我们还可以同网络编程来向远程主机守护进程发送消息,对于网络编程本书并不涉及。对于syslog( )函数,其头文件及函数原型如下:
include <syslog.h>
void openlog (const char* ident, int option, int facility);
void syslog (int pri, const char* fmt, ...);
void closelog (void);
int setlogmask (int mask);
对于setlogmask( )函数返回之前日志记录优先级屏蔽字。