标签:守护进程
在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程,都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。
守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任务,比如,作业规划进程crond,打印进程lpd等。
很多人解释daemon进程存在的理由是因为僵死进程或者输入输出,其实和这些东西一毛钱关系都没有。daemon进程存在的原因是为了防止控制终端由于某些原因(如断开终端链接)会发送一些信号导致当前工作进程异常(非期望)退出。为了让当前进程继续工作啊,于是daemon进程诞生了。
常规的守护进程编程方法:
后台运行 为避免挂起控制终端将Daemon放入后台执行。
方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。 这样控制终端就会以为进程已经终止了,同时为了下一步的setsid做准备,因为setsid要求不能是组长进程,否则会调用失败。fork之后,子进程绝不会是组长进程。
脱离控制终端,会话和进程组
先介绍一下Linux中的进程与控制终端,会话和进程组之间的关系:一个进程属于某个进程组,进程组号(GID)就是该进程组长的进程号(PID)。一个会话中包含一个或者多个进程组。这些进程组共享一个控制终端,这个控制终端通常是创建该进程的终端,比如我们的Shell。 控制终端,会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法就是调用setsid()使进程成为会话首进程 这个时候我们已经脱离原来的控制终端了,啦啦啦…
禁止进程重新打开控制终端 (这一步非必须,之所以这样做是为了进一步削弱守护进程的能力,防止其再打开一个终端)
现在,进程已经成为无终端的会话首进程。但它可以重新申请打开一个控制终端。可以通过再次fork使该进程不再成为会话组长而禁止其重新打开控制终端。
关闭打开的文件描述符
进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会系统资源浪费,造成进程所在的文件系统无法卸下以及引起无法预料的错误。
改变当前工作目录
进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。
重设文件创建掩模
进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除。
以下为一个守护进程的实例:
int daemon(void)
{
pid_t pid = fork();
if( pid != 0 ) exit(0);//父进程退出
if(setsid() == -1)//创建会话首进程
{
printf("setsid failed\n");
assert(0);
exit(-1);
}
umask(0);//清除文件掩码
pid = fork();
if( pid != 0) exit(0);//父进程退出,此时子进程不再为会话首进程,所以也不具备开启控制终端的能力
chdir ("/");//切换当前目录至根目录
for (int i = 0; i < 3; i++)//一般新开的进程就打开了3个文件描述符
{
close (i);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:守护进程
原文地址:http://blog.csdn.net/huai1693838234/article/details/47733997