守护进程

来源:互联网 发布:php curl post 文件 编辑:程序博客网 时间:2024/05/01 10:26

#include <stdio.h>

#include <stdlib.h>
#include <unistd.h>        //open()
#include <signal.h>        //sigaction()
#include <fcntl.h>        
#include <syslog.h>        //openlog()
#include <stdarg.h>        //openlog() arguments
#include <sys/time.h>        //getrlimit()
#include <sys/resource.h>    //getrlimit()
#include <sys/stat.h>        //umask()
#include <sys/types.h>        //umask
#include <string.h>
#include <errno.h>

void daemonize(const char *cmd);

int main(int argc, char *argv[])
{
    fprintf(stdout,
            "parent id:%d, parent group id: %d, parent session id: %d\n",
            getpid(), getgid(), getsid());

    daemonize("daemon");

    return 0;
}

void daemonize(const char *cmd)
{
    int i, fd0, fd1, fd2;
    pid_t pid;
    struct rlimit rl;
    struct sigaction sa;

    /*
     * Clear file creation mask; 创建守护进程第一步,设置文件创建屏蔽字
     * */
    umask(0);

    /*
     * Get maximum number of file descriptors
     * */
    if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
    {
        fprintf(stderr, "%s can't get file limit.%s\n", cmd, strerror(errno));
        exit(EXIT_FAILURE);
    }

    /*
     * Become a session leader to lose controling TTY. 创建守护进程第1.5步,创建子进程,父进程退出
     * */
    if ((pid = fork()) < 0)
    {
        fprintf(stderr, "%s can't fork:%s", cmd, strerror(errno));
        exit(EXIT_FAILURE);
    } else if (pid != 0)
    {
        //parent exit
        exit(0);
    }
//创建守护进程第3步,将子进程加入新会话,
    setsid();

    /*
     * Ensure future opens won't allocate controlling TTYs.  忽略SIGHUP信号,此信号是终端创建和退出时发生的
     * */
#if 0
    struct sigaction
    {
        void (*sa_handler) (int);
        void (*sa_sigaction) (int, siginfo_t *, void *);
        sigset_t sa_mask;
        int sa_flags;
        void (*sa_restorer) (void);
    };
#endif
    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if(sigaction(SIGHUP, &sa, NULL) < 0)
    {
        fprintf(stdout, "%s can't ignore SIGUP\n", cmd);

        exit(EXIT_FAILURE);

    }

 if((pid = fork()) < 0)   //创建守护进程第2步,创建子进程,父进程退出
    {
        fprintf(stderr, "%s can't fork:%s", cmd, strerror(errno));
        exit(EXIT_FAILURE);
    }
    else if(pid != 0)
    {
        //parent exit.
        exit(0);
    }

    /*
     * Change the current workint directory to the root so we won't prevent
     * file systems from begin unmounted.创建守护进程第4步,改变工作路径到根,预防文件系统卸载
     * */
    if(chdir("/") < 0)
    {
        fprintf(stderr, "%s: can't change directory to /\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

    /*
     * Close all open file descriptors, RLIM_INFINITY is 资源无限制,创建守护进程第5步,关闭所有的文件描述符
     * */
    if(rl.rlim_max == RLIM_INFINITY)
    {
        rl.rlim_max = 1024;
    }
    for(i = 0; i < rl.rlim_max; ++i)
    {
        close(i);
    }

    /*
     * Attach file descriptors 0, 1, and 2 to /dev/null.创建守护进程第6步,重定向0,1,2到/dev/null
     * */
    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);

    /*
     * Initialize the log file.
     * */
    openlog(cmd, LOG_CONS, LOG_DAEMON);
    if(fd0 !=0 || fd1 != 1 || fd2 != 2)
    {
        syslog(LOG_ERR, "unexcptioned file descriptors %d %d %d",fd0, fd1, fd2);
        exit(1);
    }
}
原创粉丝点击