守护进程

来源:互联网 发布:nvh 软件 编辑:程序博客网 时间:2024/05/01 16:25

守护进程

守护进程概述:

       守护进程(Dameon)是Linux 中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种人物或者等待处理某些发生的事件。守护进程常在系统引导装入时启动,在系统关闭时终止。Linux系统中有很多守护进程,如:作业规划进程crond、打印进程lqd 等(这里的结尾字母 d  就是Dameon 的意思)。

       一般的进程在终端关闭的时候都会自动关闭,但是守护进程却不因终端的关闭而关闭,除非系统关闭了,否则守护进程一直都存在。如果想让某个进程不因为用户或者终端或其他变化而受到影响,那么就必须把这个进程变成一个守护进程。

编写守护进程:

创建守护进程的流程一般比较固定,掌握了流程,守护进程的编写就非常简单了,一般由五个步骤来完成。

1、创建子进程后,父进程立刻退出

————————————————————————————————————————————

pid_t  pid = fork();

if(pid > 0)

       exit(0);

————————————————————————————————————————————

       在Linux 系统中父进程先于子进程退出会造成子进程成为孤儿进程,而每当系统发现一个孤儿进程时,就会自动由1号进程(init)收养它,这样原先的子进程就会变成init进程的子进程。

2、在子进程中创建会话

使用系统函数setsid来创建会话。

setsid函数的作用

(1)让进程摆脱原会话的控制

(2)让进程摆脱原进程组的控制

(3)让进程摆脱原控制终端的控制

       为什么要调用setsid 函数呢?由于创建守护进程的第一步调用了 fork 函数来创建子进程,再将父进程退出。由于调用了fork 函数,子进程全盘拷贝了父进程的会话期、进程组、控制终端等,虽然父进程退出了,但会话期、进程组、控制终端等并没有改变,因此,还不是真正意义的独立开来,而setsid 函数能够使进程完全独立出来,从而摆脱其他进程的控制。

3、改变工作目录

      使用fork 创建的子进程继承了父进程的当前工作目录。由于在进程运行中,当前目录所在的文件系统是不能卸载的,这对以后工作会造成诸多的麻烦。因此,通常的做法是让 “/” 作为守护进程的当前工作目录,这样就可以避免上述的问题了。当然,也可以改为其他路径,如“/tmp”。改变工作目录的常见函数式 chdir。这里我们调用 chdir(/);

4、重设文件权限掩码

     文件权限掩码是指屏蔽掉文件权限中的对应位。由于使用 fork 函数创建的子进程继承了父进程的文件权限掩码,这也给子进程使用文件带来诸多的麻烦。因此,通常把文件权限重设为0,这样可以大大增强守护进程的灵活性。设置文件权限掩码的函数umask。在这里,我们使用 umask(0),从而不会屏蔽文件权限中的任何对应位。

5、关闭任何不需要的文件描述符

      用 fork 函数新建的子进程会从父进程那里继承一些已经打开了的文件,而这些打开的文件可能永远不会被守护进程读写,这样就造成了一些资源的浪费。根据上面所说的,守护进程是和终端脱离关系的,因此我们肯定用不到输入、输出、报错这三个文件。它们对应的文件描述符分别为0、1、2。因此至少要关闭这三个打开的文件描述符。在这里我们一般这样子做:

——————————————————————————————————————————

#define  MAXFILE    XXX   /*  XXX 表示你想关闭多少文件 */

for(i = 0; i < MAXFILE; i++)

       close(i)

——————————————————————————————————————————

实例分析:创建一个守护进程dameon 每5秒向新建的text.txt文件里输入信息

<代码示例>

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>


#define MAXFILE 65535

int main()
{
   pid_t pid;
   int i,fd,len;
   char *buf="This is a damenon.\n";
   len = strlen(buf)+1;
 
   pid=fork();
   if(pid<0)
   {
        printf("fork error.\n");
        exit(1);
   }
   else if(pid>0)
   {
        printf("That is a father process,it will be exit soon.\n");
        exit(0); //第一步,创建子进程后,父进程立刻退出
   }
   setsid();    //第二步,创建会话
   chdir("/");  //第三步,更改目录
   umask(0);    //第四步,重设掩码为0
   for(i=0;i<MAXFILE;i++)
       close(i); //关闭所有文件
   while(1)
   {

       /*新建一个用来储存信息的test.txt的文件*/
       if((fd=open("/home/process_test/test.txt",O_CREAT|O_WRONLY|O_APPEND,0600))<0)
       {
            perror("open");
            exit(1);
       }
       write(fd,buf,len); /*为简洁,这里省去了一些可能失败的判断*/
       close(fd);
       sleep(5);
   }
}

 

原创粉丝点击