守护进程

守护进程是一种后台运行并且独立于所有终端控制之外的进程,
这些进程不会被终端所产生的中断信号所打断,也不会在终端输出信息。
它们执行着各种系统服务和管理的任务。

一.守护进程的启动
要启动一个守护进程,可以采取以下几种方式:
1.以系统启动期间通过系统的初始化脚本启动,
通过这种方式启动的守护进程具有超级用户的权限,
系统的一些基本服务通常都是通过这种方式启动的。
2.由cron 定时启动的处理程序
3.由at 启动的处理程序
4.在终端上用 & 启动的程序
5.在终端上用 nohup 启动的程序,以这种方式启动的进程,
在用户退出后,仍会继续运行。

二.守护进程的错误输出
守护进程不属于任何终端,所以当需要输出某些信息时,
它无法像普通进程那样将信息直接输出到标准输出和标准错误中,
为了解决这个问题,linux 系统提供了syslog() 系统调用,
通过它,守护进程可以向系统的log 文件写入信息。
该函数在 syslog.h 中声明如下:
void syslog(int priority, char *format,...);
其中priority 参数指明了进程要写入信息的等级和用途:
priority 等级的取值
等级 值 描述
LOG_EMERG 0 系统崩溃
LOG_ALERT 1 必须立即处理的动作
LOG_CRIT 2 危急的情况
LOG_ERR 3 错误
LOG_WARNING 4 警告
LOG_NOTICE 5 正常,但值得注意的情况(default)
LOG_INFO 6 信息
LOG_DEBUG 7 调试信息

如果没有指定等级,则缺省为 LOG_NOTICE。
priority 用途的取值
用途 描述
LOG_AUTH 安全/管理信息
LOG_AUTHPRIV 安全/管理信息(私人信息)
LOG_CRON cron守护进程
LOG_DAEMON 系统守护进程
LOG_FTP ftp守护进程
LOG_KERN 内核守护进程
LOG_LOCAL0 ~ LOG_LOCAL7 local user
LOG_LPR 行打印机系统
LOG_MAIL mail 系统
LOG_NEWS network news 系统
LOG_SYSLOG syslogd 进程产生的信息
LOG_USER 随机用户信息(default)
LOG_UUCP UUCP系统

如果没有指定用途,缺省为LOG_USER
syslog 调用后面的参数用法和printf 类似。例如:
syslog(LOG_INFO | LOG_LOCAL, "rename(%s,%s):%m",file1,file2);
需要注意的是,最后需要指定一个 %m ,其对应着errno 错误码。
在一个进程使用syslog()前,应该先使用openlog() 打开系统记录.
openlog 在syslog.h 中声明如下:
void openlog(const char *ident, int options, int facility);
参数ident 将被加在所有用syslog 写入的信息前,
通常这个参数是程序的名字。
参数options 的取值及含义:
取值 描述
LOG_CONS 如果不能写入log 信息,则直接将其发往主控制台
LOG_NDELAY 直接建立与syslogd 进程的连接而不是打开log 文件
LOG_PERROR 将信息写入log 的同时也发送到标准错误输出
LOG_PID 在每个信息中加入PID 信息
参数facility 指定了syslog 调用的缺省用途值。
在使用完log 之后,可以使用系统调用closelog 来关闭它:
void closelog(void);

三.守护进程的建立
1.fork
首先需要在fork 一个子进程并将其父进程关闭, 如果进程是作为一个
shell 命令在命令行上前台启动的,当父进程终止时,
shell 就认为该命令已经结束,这样子进程就自动成为了后台进程,
而且子进程从父进程那里继承了组标识符同时又拥有了自己的进程标识符,
这样保证了子进程不会是一个进程组的首进程,这一点是下一步必须的。
2.setsid
setsid() 调用创建了一个新的进程组,调用进程成为了该进程组的首进程,
这样,就使该进程脱离了原来的终端,成为了独立于终端外的进程。
3.忽略SIGHUP 信号,重新fork
这样使进程不再是进程组的首进程,可以防止在某些情况下进程
意外的打开终端而重新与终端发生联系。
4.改变工作目录,清除文件俺码
改变工作目录主要是为了切断进程与原有文件系统的联系,
并且保证无论从什么地方启动进程都能正常地工作,
清除文件掩码是为了消除进程自身俺码对其创建文件的影响
5.关闭全部已打开的文件句柄
这是为了防止子进程继承了在父进程中打开的文件,
而使这些文件始终保持打开从而产生某些冲突。
6.打开log 系统

以上就是建立一个守护进程的基本步骤,
通过上面几步,我们就可以正确地建立自己的守护进程。
下面举个简单的例子:
#include<sys/types.h>
#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())/*终止父进程*/
		exit(0);
	setsid();/*新建进程组*/
	signal(SIGHUP, SIG_IGN);/*忽略SIGHUP信号*/
	if(pid = fork())/*终止第一子进程*/
		exit(0);
	chdir("/");/*改变工作目录*/
	umask(0);/*清除文件掩码*/
	for(i=0;i<MAXFD;i++)/*关闭所有文件句柄*/
		close(i);
	openlog(pname, LOG_PID, facility);/*打开log*/

}

你可能感兴趣的:(守护进程)