Linux守护进程

来源:互联网 发布:如何通过ip找到域名 编辑:程序博客网 时间:2024/06/06 02:07

        在公司做项目的时候为了防止服务器中的bug导致程序崩溃,通常情况下需要一个进程负责监控你的服务器程序即使发生崩溃的情况也能在第一时间将服务器重启不至于会发生服务器程序崩溃而再也无法启动的情况。为此,我写了一个监测程序,采用守护进程的方式来实现。

守护进程是一种在后台运行的特殊进程,它脱离了终端从而避免进程被任何终端所产生的信号所打断。

守护进程有以下几个要点:

      1. 屏蔽一些有关控制终端的操作信号。这是为了防止守护进程在运行起来之前控制终端受到干扰而挂起。

      for(inti=0;i<31;i++)

      {

        signal(SIGTTOUT,SIG_IGN);

      }

      2.  在后台运行。方法是创建子进程,并让父进程退出,使子进程在后台运行

     if(pid==fork())

     {

         exit(0);

     }

    3.  脱离控制终端和进程组。方法是需要调用setsid()函数使子进程形成新的会话组组长。

           setsid();

   4.  禁止进程重新打开终端。当进程已经成为了无终端的会话组组长了之后它依然可以申请重新打开一个终端。方法是再创建一次子进程。并让父进程退出,那么该子进程就不         再是会话组的组长了,就无权再打开终端。

             if(pid=fork)

                   exit(0);

    5. 关闭打开的文件描述符,包括标准的输入输出,如果不关闭会造成资源的浪费。  还会造成进程所在的文件系统无法卸载造成无法预料的错误。

          #define NOFIFLE 256  //不同的系统有不同的限制

          for(int i=0;i<NOFIFLE;i++)

         {

               close(i);

         }

   6. 重设文件创建掩码。因为子进程从创建它的父进程那里继承了文件创建掩码,它          可能修改守护进程所创建的文件存取权限。所以要将文件创建掩码清除。

            umask(0);

   7. 处理子进程退出信号,让系统负责回收子进程退出时产生的僵尸。

           signal(SIG_CHLD,SIG_IGN);

 

      以下是我用守护进程的方式写的一个服务器监控程序,它负责去启动指定的程序,并对其进行监控,一旦程序异常退出或崩溃,监控程序立即将它重启:

        

#include <QtCore/QCoreApplication>#include <unistd.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/wait.h>#include <QFile>//#define ARM_LIFECUBE#define NUM_FILE 256#define NOW_DIR "/data/local/KD"#define TOOL_PATH "/data/local/KD/tool"#define TOOL "tool"#define DNS_PATH "/data/local/KD/qtdns"#define DNS "qtdns"#ifndef ARM_LIFECUBE#define SERVER_PATH "/data/local/KD/itoneserver"#define SERVER "itoneserver"#else#define SERVER_PATH "/data/local/KD/LifeCube"#define SERVER "LifeCube"#endifvoid startGuard(const char *strPath,const char *strProcess){    QFile filePath(strPath);    if(!filePath.exists())        return;    if(filePath.size()<=0)        return;    if(access(strPath,X_OK) != 0)        return;    int pidGuard = fork();    if(pidGuard == 0)    {       execl(strPath,strProcess,NULL);    }    else if(pidGuard > 0)    {       waitpid(pidGuard,NULL,0);       startGuard(strPath,strProcess);    }    else    {      exit(EXIT_FAILURE);    }}int main(int argc, char *argv[]){    QCoreApplication a(argc, argv);    signal(SIGTTOU,SIG_IGN);    signal(SIGTTIN,SIG_IGN);    signal(SIGTSTP,SIG_IGN);    signal(SIGHUP,SIG_IGN);    //忽略输入,输出,停止,挂起,信号    int pid = fork();    if(pid > 0)        exit(EXIT_SUCCESS);    else if(pid < 0)        exit(EXIT_FAILURE);    //保证在后台运行    else    {        setsid();//新建进程组        pid = fork();        if(pid >0 )        {            exit(EXIT_SUCCESS);//禁止进程重新打开控制终端        }        else if(pid < 0)        {            exit(EXIT_FAILURE);        }        else        {            for(int i = 0;i<NUM_FILE;i++)                close(i);            chdir(NOW_DIR);            umask(0);//重建文件创建掩码            signal(SIGCHLD,SIG_IGN);//忽略子进程退出信号            /*            pid_t pidGuard = fork();            if(pidGuard == 0)            {                startGuard(DNS_PATH,DNS);            }            else if(pidGuard < 0)            {               exit(EXIT_FAILURE);            }            */            //主进程            pid_t pidServer = fork();            if(pidServer == 0)            {                startGuard(SERVER_PATH,SERVER);            }            else if(pidServer < 0)            {               exit(EXIT_FAILURE);            }            //主进程            pid_t pidTool = fork();            if(pidTool == 0)            {               startGuard(TOOL_PATH,TOOL);            }            else if(pidTool < 0)            {               exit(EXIT_FAILURE);            }        }    }    return a.exec();}

0 0
原创粉丝点击