1、概念理解:
守护进程(Daemon)是运行在后台的一种特殊进程,也称为精灵进程。是生存期较长的一种进程,常常在系统自举时启动,仅在系统关闭时终止。没有控制终端,仅仅在后台运行,Linux有很多守护进程执行日常事务活动,是不受终端控制的进程。
2、守护进程作用:
Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任 务。比如,作业规划进程crond,打印进程lpd等。
守护进程的编程本身并不复杂,复杂的是各种版本的Unix的实现机制不尽相同,造成不同Unix环境下守护进程的编程规则并不一致。
3、守护进程特征总结:
后台运行
守护进程必须与其运行前的环境隔离开来❶
守护进程的启动方式特殊❷
❶
这些环境包括未关闭的 文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。
❷
它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由用户终端 (通常是shell)执行。
除开以上这些特殊性以外,守护进程与普通进程基本上没有什么区别。因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。如果读者对进程有比较深入的认识就更容易了。
4、守护进程编写:
不同Unix环境下守护进程的编程规则并不一致。所幸的是守护进程的编程原则其实都一样,区别在于具体的实现细节不同。这个原则就是要满足守护 进程的特性。
守护进程的编写以及步骤:
1.fork子进程,而后父进程退出,此时子进程会被init进程接管。
2.修改子进程的工作目录、创建新进程组和新会话、修改umask。
3.子进程再次fork一个进程,这个进程可以称为孙子进程,而后子进程退出。
4.重定向孙子进程的标准输入流、标准输出流、标准错误流到/dev/null。
完成上面的4个步骤,那么最终的孙子进程就称为守护进程。
#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;
pit_t pid;
/*fork()一个子进程,并终止父进程*/
if(pid=fork())
{
exit(0);
}
/*setsid()调用创建了一个新的进程组,调用进程成为该进程组的首进程。
这样,就使该进程脱离原来的终端,成为了独立终端外的进程*/
setsid();
/*忽略SIGHUP信号,重新fork。
这样使进程不再是进程组的首进程,可以防止在某些情况下进程意外的打开终端而重新与终端发生联系。*/
signal(SIGHUP,SIG_IGN);
if(pid=fork()) //fork()终止第一子进程
exit(0);
/*第二子进程*/
daemon_proc = 1;
/*改变工作目录,清楚文件掩码。
改变工作目录主要是为了切断进程与原有文件系统的联系。
并且保证无论从什么地方启动进程都能正常工作。清除文件掩码是为了消除进程自身掩码对其创建文件的影响。*/
chdir("/"); //将工作目录设定位“/”
umask(0);
/* 关闭全部已打开的文件句柄。
这是为了防止子进程继承在父进程中打开的文件而使这些文件始终保持打开从而产生某些冲突。*/
for(i = 0; i<MAXFD; i++){
close(i);
}
/*打开log系统*/
openlog(pname, LOG_PID, facility);
}