13.1 引言
守护进程(daemon)是生存期长的一种进程。它们常常在系统引导装入时启动,仅在系统关闭时才终止。因为它们没有控制终端,所以说它们是在后台运行的。
13.2 守护进程的特征
系统进程依赖于操作系统实现。父进程ID为0的各进程通常是内核进程,它们作为系统引导装入过程的一部分而启动。(init是个例外,它是一个由内核在引导装入时启动的用户层次的命令)内核进程是特殊的,通常存在于系统的整个生命期中。它们以超级用户特权运行,无控制终端,无命令行。
进程1通常是init,它是一个系统守护进程,除了其他工作外,主要负责启动各运行层次特定的系统服务。
13.3 编程规则
- 调用
umask
将文件模式创建屏蔽字设置为一个已知值(通常是0); - 调用
fork
,然后使父进程exit
; - 调用
setsid
创建一个新会话; - 将当前工作目录更改为根目录;
- 关闭不再需要的文件描述符;
- 某些守护进程打开/dev/null使其具有文件描述符0、1和2,这样,任何一个试图读标准输入、写标准输出或标准错误的库例程都不会产生任何效果。
13.4 出错记录
syslog设施是一个集中的守护进程出错记录设施。
有以下3种产生日志消息的方法:
(1)内核例程可以调用log
函数。任何一个用户进程都可以通过打开(open
)并读取(read
)/dev/klog设备来读取这些消息;
(2)大多数用户进程(守护进程)调用syslog
函数来产生日志消息;
(3)无论一个用户进程是在此主机上,还是在通过TCP/IP网络连接到此主机的其他主机上,都可将日志消息发向UDP端口514。
该设施的接口时syslog
函数:
#include <syslog.h>
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
int setlogmask(int maskpri);
// 返回值:前日志记录优先级屏蔽字值
- 调用
openlog
是可选择的,如果不调用openlog
,则在第一次调用syslog
时,自动调用openlog
; - 调用
closelog
也是可选择的,因为它只是关闭曾被用于与syslogd守护进程进行通信的描述符; - 调用
openlog
可以指定一个ident,此后,此ident将被加至每则日志消息中,ident一般是程序的名称;option参数是指定各种选项的位屏蔽,可用值如下:
openlog
的facility参数值取自下图,设置facility参数的目的是可以让配置文件说明,来自不同设施的消息将以不同的方式进行处理;如果不调用openlog
,或者以facility为0来调用它,那么在调用syslog
时,可将facility作为priority参数的一个部分进行说明;
- 调用
syslog
产生一个日志消息,其priority参数是facility和level的组合,它们可选取的值分别列于facility(图13-4)和level(图13-5)中,level值的优先级从最高到最低依次排列;
- 将format参数以及其他所有参数传至
vsprintf
函数以便进行格式化。在format中,每个出现的%m
字符都先被代换成与errno值对应的出错消息字符串(strerror
); setlogmask
函数用于设置进程的记录优先级屏蔽字,它返回调用它之前的屏蔽字。
除了syslog
,很多平台还提供它的一种变体来处理可变参数列表:
#include <syslog.h>
#include <stdarg.h>
void vsyslog(int priority, const char *format, va_list arg);
13.5 单实例守护进程
- 文件和记录锁机制保证一个守护进程只有一个副本在运行;
- 如果每一个守护进程创建一个有固定名字的文件,并在该文件的整体上加一把写锁,那么只允许创建一把这样的写锁;
- 如果守护进程在一个文件的整体上得到一把写锁,那么在该守护进程终止时,这把锁将被自动删除。
13.6 守护进程的惯例
- 若守护进程使用锁文件,那么该文件通常存储在/var/run目录中,锁文件的名字通常是name.pid,其中,name是该守护进程或服务的名字;
- 若守护进程支持配置选项,那么配置文件通常存放在/etc目录中,配置文件的名字通常是name.conf,其中,name是该守护进程或服务的名字;
- 守护进程可用命令行启动,但通常它们是由系统初始化脚本之一(
/etc/rc*
或/etc/init.d/*
)启动的,如果在守护进程终止时,应当自动地重新启动它; - 若一个守护进程有一个配置文件,那么当该守护进程启动时会读该文件,但在此之后一般就不会再查看它,如果配置文件被修改,需要重启守护进程,使配置文件更改生效。
13.7 客户进程-服务器进程模型
- 守护进程常常用作服务器进程;
- 一般而言,服务器进程等待客户进程与其联系,提出某种类型的服务请求;
- 客户进程向服务器进程发送请求,服务器进程则向客户进程回送应答。
13.8 实例代码
chapter13