守护进程也称为精灵进程,是一种运行在后台的特殊进程,它不存在控制终端,并周期性地执行某项任务或等待处理某项任务。
守护进程特点:
l 所有的守护进程都是以超级用户启动的(UID为0);
l 没有控制终端(TTY为?);
l 终端进程组ID为-1(TPGID表示终端进程组ID,该值表示与控制终端相关的前台进程组,如果未和任何终端相关,其值为-1;
l 所有的守护进程的父进程都为init进程(PID为1的进程)。
Linux中实现守护进程:
1. 让init进程成为新产生进程的父进程;
调用fork函数创建子进程后,使父进程立即退出。从而使产生的子进程将变成孤儿进程,并被init进程接管,同时,所产生的新进程将变为在后台运行;
2. 调用setsid函数
通过调用setsid函数,使得新创建的进程脱离控制终端,同时创建新的进程组,并成为该进程组的首进程。
在Linux中,所有的进程都属于各自的进程组。进程组是一个或多个进程的集合。进程组ID是由领头进程的进程号决定的,每个进程组都存在一个领头进程。进程组的存在与否与领头进程是否存在没有关系。
会话是一个或多个进程组的集合。与进程组类似,每个会话都存在一个领头进程。会话和进程组是Linux内核用于管理多用户情况下用户进程的方法。每个进程都属于一个进程组,而进程组又属于某个会话。当用户从终端或伪终端登录系统,系统会创建一个新的会话。在该终端上启动的进程都会被系统划归到会话的进程组中。
会话中的进程通过该会话中的领头进程(常称其为控制进程)与一个终端相连。该终端是会话的控制终端。一个会话只能有一个控制终端,反之一样。如果会话存在一个控制终端,则它必然拥有一个前台进程组。属于该组的进程可以从控制终端获得输入。这时,其他的进程组都为后台进程组。如下图所示:
由于守护进程没有控制终端,而使用fork函数创建的子进程继承了父进程的控制终端、会话和进程组,因此,必须创建新的会话,以脱离父进程的影响。Linux提供了setsid函数创建新的会话。
pid_t setsid(void);
setsid函数将创建新的会话,并使得调用setsid函数的进程成为新会话的领头进程。
3. 更改当前工作目录
一般将工作目录更改到根目录下(/目录)。
4. 关闭文件描述符,并重定向标准输入、输出和错误输出
关闭从父进程继承的某些打开的文件描述符,使用dup函数将标准输入、输出和错误输出重定向到/dev/null设备上。
5. 设置守护进程的文件权限创建掩码
umask修改文件权限。
守护进程日志实现
syslogd守护进程通过接收其他守护进程的信息,并将这些信息记录在/etc/syslog.conf指定的位置,同时会根据消息级别判断是将消息记录在日志文件,还是显示在用户终端上。它负责记录、发送系统或工具所产生的信息,配置文件时/etc/syslog.conf。
syslog.conf文件中配置行的语法:【消息类型】【TAB分隔符】【处理方案】。
消息类型包括facility和level两个部分,之间以”.”隔开。通过指定facility和level的取值,可以使facility在大于或等于该优先级的时候才记录相关日志信息。
syslogd守护进程用于解决守护进程的日志记录问题,守护进程日志主要涉及3个函数,分别是openlog、syslog和closelog函数:
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, …);
void closelog(void);
openlog函数用于打开系统日志连接。closelog用于关闭打开的系统日志连接。
由于守护进程的特点,它往往作为服务器进程。守护进程是工作在Client/Server模式的一种特殊进程。