1 简介
是一种后台运行并且独立于所有终端控制之外的进程 。
2 守护进程的启动
1》.在系统期间通过系统的初始化脚本启动守护进程。这些脚本通常在目录etc/rc.d 下;
2》.很多网络服务程序是由inetd 守护程序启动的。它监听各种网络请求;
3》.由cron 定时启动的处理程序;
4》.由at 启动的处理程序;
5》.守护程序也可以从终端启动;
6》.在终端上用nohup 启动的进程;
3 守护进程的错误输出
守护进程可以向系统的
log 文件写入信息,
函数库syslog.h 中的定义如下:
void syslog( int priority, char *format, ...);
表3-2 priority 等级取值及其含义
等级 值 描述
LOG_EMERG
0
系统崩溃(最高优先级)
LOG_ALERT
1
必须立即处理的动作
LOG_CRIT
2
危急的情况
LOG_ERR
3
错误
LOG_WARNING
4
警告
LOG_NOTICE
5
正常但是值得注意的情况(缺省)
LOG_INFO
6
信息
LOG_DEBUG 7 调试信息(最低优先级)
表3-3 priority 用途的取值及其含义
用途 描述
LOG_AUTH 安全/管理信息
LOG_AUTHPRIV 安全/管理信息(私人)
LOG_CRON cron 守护进程
LOG_DAEMON 系统守护进程
LOG_FTP ftp 守护进程
LOG_KERN 内核守护进程
LOG_LOCAL0 local use
LOG_LOCAL1 local use
LOG_LOCAL2 local use
LOG_LOCAL3 local use
LOG_LOCAL4 local use
LOG_LOCAL5 local use
LOG_LOCAL6 local use
LOG_LOCAL7 local use
LOG_LPR 行打印机系统
LOG_MAIL mail 系统
LOG_NEWS network news 系统
LOG_SYSLOG syslogd 进程产生的信息
LOG_USER 随机用户信息(缺省)
LOG_UUCP UUCP 系统
syslog()调用后面的参数用法和printf()类似,例子:
syslog(LOG_INFO|LOG_LOCAL2,”rename(%s,%s): %m”,file1,file2);
在一个进程使用syslog()的时候,应该先使用openlog()打开系统记录:
#include <syslog.h>
void openlog(const char *ident, int options, int facility);
参数ident 是一个字符串通常这个参数是程序的名字。
参数options 可以是表3-4 这些参数或是它们的或(|)的结果:
表3-4 option 的取值及其含义
参数 描述
LOG_CONS 如果不能写入log 信息,则直接将其发往主控台
LOG_NDELAY 直接建立与syslogd 进程的连接而不是打开log 文件
LOG_PERROR 将信息写入log 的的同时也发送到标准错误输出
LOG_PID 在每个信息中加入pid 信息。
在使用完log 之后,可以使用系统调用closelog()来关闭它:
void closelog(void);
4. 守护进程的全部过程:
#include <signal.h>
#include <unistd.h>
#include <syslog.h>
#define MAXFD 64
void daemon_init(const char *pname, int facility)
{
int i:
pid_t pid;
if (pid=fork()) /* fork,终止父进程 */
exit(0);
/* 第一子进程 */
setsid();
signal(SIGHUP,SIG_IGN);
/* fork,终止第一子进程 */
if (pid=fork())
exit(0);
/* 第二子进程 */
daemon_proc=1;
/* 将工作目录设定为"/" */
chdir("/");
/* 清除文件掩码 */
umask(0);
/* 关闭所有文件句柄 */
for (i=0;i<MAXFD;i++)
{
close(i);
}
5.解释
#include <signal.h>
#include <unistd.h>
#include <syslog.h>
#define MAXFD 64
void daemon_init(const char *pname, int facility)
{
int i:
pid_t pid;
if (pid=fork()) /* fork,终止父进程 */
exit(0);
/* 第一子进程 */
setsid();
signal(SIGHUP,SIG_IGN);
/* fork,终止第一子进程 */
if (pid=fork())
exit(0);
/* 第二子进程 */
daemon_proc=1;
/* 将工作目录设定为"/" */
chdir("/");
/* 清除文件掩码 */
umask(0);
/* 关闭所有文件句柄 */
for (i=0;i<MAXFD;i++)
{
close(i);
}
5.解释
1.fork
首先需要fork 一个子进程并将父进程关闭。如果进程是作为一个shell 命令在命令行上前台启动的,当父进程终止时,shell 就认为该命令已经结束。这样子进程就自动称为了后台进程。而且,子进程从父进程那里继承了组标识符同时又拥有了自己的进程标识符,这样保证了子进程不会是一个进程组的首进程。这一点是下一步setsid 所必须的。
首先需要fork 一个子进程并将父进程关闭。如果进程是作为一个shell 命令在命令行上前台启动的,当父进程终止时,shell 就认为该命令已经结束。这样子进程就自动称为了后台进程。而且,子进程从父进程那里继承了组标识符同时又拥有了自己的进程标识符,这样保证了子进程不会是一个进程组的首进程。这一点是下一步setsid 所必须的。
2.setsid
setsid()调用创建了一个新的进程组,调用进程成为了该进程组的首进程。这样,就使
该进程脱离了原来的终端,成为了独立于终端外的进程。
该进程脱离了原来的终端,成为了独立于终端外的进程。
3.忽略SIGHUP 信号,重新fork
这样使进程不在是进程组的首进程,可以防止在某些情况下进程意外的打开终端而重新与终端发生联系。
这样使进程不在是进程组的首进程,可以防止在某些情况下进程意外的打开终端而重新与终端发生联系。
4.改变工作目录,清除文件掩码
改变工作目录主要是为了切断进程与原有文件系统的联系。并且保证无论从什么地方启动进程都能正常的工作。清除文件掩码是为了消除进程自身掩码对其创建文件的影响。
改变工作目录主要是为了切断进程与原有文件系统的联系。并且保证无论从什么地方启动进程都能正常的工作。清除文件掩码是为了消除进程自身掩码对其创建文件的影响。
5.关闭全部已打开的文件句柄
这是为了防止子进程继承了在父进程中打开的文件而使这些文件始终保持打开从而产生某些冲突。
这是为了防止子进程继承了在父进程中打开的文件而使这些文件始终保持打开从而产生某些冲突。
6.打开log 系统
以上就是建立一个守护进程的基本步骤。当然,一个实际的守护进程要比这个例子复杂许多,但是万变不离其宗,原理都是相同的。通过上面几步,我们可以正确的建立自己的守护进程。
以上就是建立一个守护进程的基本步骤。当然,一个实际的守护进程要比这个例子复杂许多,但是万变不离其宗,原理都是相同的。通过上面几步,我们可以正确的建立自己的守护进程。