守护进程

一、标准步骤

  创建守护进程大概分以下几步,但是还要关闭一些文件描述符才行:

#include <unistd.h>  
#include <stdio.h>
#define RUNNING_DIR /tmp
int main(){
    pid_t pid;
    pid=fork();
    if(pid!=0)exit(0); // 如果创建失败或者为父进程则退出
    printf("Running...");
    setsid();          // obtain a new process grop
    for(int i=gettabsize();i>=0;i--){close(i);}
    i=open("/dev/null",O_RDWR);
    dup(i); dup(i);
    umask(027);
    chdir(RUNNING_DIR);
    
    signal(SIGCHLD,SIG_IGN);
    signal(SIGTSTP,SIG_IGN);
    signal(SIGTTOU,SIG_IGN);
    signal(SIGTTIN,SIG_IGN);
    signal(SIGHUP,HelperDaemon::signalHandler);  // hangup
    signal(SIGTERM,HelperDaemon::signalHandler); // kill
    while(1); return 0; 
}

  沉默,不进行标准输出:参考

  关于dup: 参考   参考

  谷歌图书:参考   参考

  守护进程中setsid、nohub等的参考资料:参考

二、实例

#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>

class WSDaemon
{
public:
    WSDaemon(){}
    ~WSDaemon(){}
    void daemonize();
    void wsExit(std::string cause, int code)
    {
        std::cerr << cause << std::endl;
        exit(code);
    }
};

#if 1
void WSDaemon::daemonize()
{
    int pid;
    int i;
    
    if(getppid() == 1)
    {
        return;    //wsExit("already running.", 0);
    }

    // 1. fork
    pid = fork();
    std::cout << pid << std::endl;

    if(pid < 0)
        wsExit("fork error.", 1);

    if(pid > 0)
        exit(0);
        //wsExit("parent exit.", 0);

    // 2. child process detach from parent and creat new session
    setsid();
    
    // 3. switch to a working directory that cannot be uninstalled.
    if(chdir("/") < 0) wsExit("change dir error.", 1);

    // 4. change the file permission mask to prevent inheriting to the parent process permission, result in file operation failure.
    // (~0) & mode == 0777 & mode
    // 0777 : 0B777 
    umask(0);
    
    // 5. close file description inherited from parent process.
    for(i=0; i < NOFILE; i++) close(i);
    
    // 6. redirect standard output to prevent byte stream from accidentally outputting from terminal. 
    /*
    i = open("/dev/null", O_RDWR);
    dup(i);
    dup(i);
    */

    return;
}
#endif


#if 0
void WSDaemon::daemonize()
{
    int i;
    if(getppid() ==1)
    {
        std::cerr << "There is already a daemon running." <<std::endl;
        return;
    }

    i = fork();

    if(i<0) exit(1);
    if(i>0) exit(0);

    setsid();

    for(i = getdtablesize();i>=0;i--)
    {
        close(i);
    }
    
    i = open("/dev/null", O_RDWR);
    dup(i);
    dup(i);
    umask(027);
    chdir("/tmp");
}

#endif


int main()
{
    FILE *fp;
    time_t t;

    WSDaemon wsd;
    wsd.daemonize();

    while(1)
    {
        // wait 5s
        sleep(5);
        fp = fopen("/home/alex/Desktop/webs-qt-Online/test.log", "a+");
        if(fp >= 0)
        {
            time(&t);
            fprintf(fp, "current time is : %s\n", ctime(&t));
            fclose(fp);
        }
    }
    return 0;
}
View Code

 

posted @ 2019-08-23 11:41  AlexOne  阅读(252)  评论(0编辑  收藏  举报