zoukankan      html  css  js  c++  java
  • linux守护进程范例

    1. 目标

    让程序脱离控制终端,不从终端接收信号,防止被外部信号打扰。

    2. 标准过程

    1. fork()出子进程, 父进程退出
    2. setsid()新建会话组,子进程脱离控制终端
    3. 关闭标准输入输出
      标准过程就上边3步,还可以umask(0), chdir() 或者再fork()一次,得到孙子进程,不过不是必须的。

    3. 示例

    nginx的过程

    ngx_int_t
    ngx_daemon(ngx_log_t *log)
    {
        int  fd;
    
        switch (fork()) {
        case -1:
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
            return NGX_ERROR;
    
        case 0:
            break;
    
        default:    // 把父进程退掉
            exit(0);
        }
    
        ngx_pid = ngx_getpid();
    
        // 变为新session
        if (setsid() == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
            return NGX_ERROR;
        }
    
        // 清除文件创建默认限制
        umask(0);
    
        fd = open("/dev/null", O_RDWR);
        if (fd == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                          "open("/dev/null") failed");
            return NGX_ERROR;
        }
    
        // STDIN_FILENO经过dup2后也指向fd了,也就是说,没有输入了
        if (dup2(fd, STDIN_FILENO) == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
            return NGX_ERROR;
        }
    
        // 这里也就是说,没有输出了
        if (dup2(fd, STDOUT_FILENO) == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
            return NGX_ERROR;
        }
    
    #if 0
        if (dup2(fd, STDERR_FILENO) == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
            return NGX_ERROR;
        }
    #endif
    
        if (fd > STDERR_FILENO) {
            if (close(fd) == -1) {
                ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
                return NGX_ERROR;
            }
        }
    
        return NGX_OK;
    }
    

    glibc的daemon()函数

    int
    daemon(int nochdir, noclose)
    {
        int fd;
    
        switch (fork()) {
        case -1:
            return (-1);
        case 0:
            break;
        default:
            _exit(0);
        }
    
        if (__setsid() == -1)
            return (-1);
    
        if (!nochdir)
            (void)__chdir("/");
    
        if (!noclose && (fd = __open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
            (void)__dup2(fd, STDIN_FILENO);
            (void)__dup2(fd, STDOUT_FILENO);
            (void)__dup2(fd, STDERR_FILENO);
            if (fd > 2)
                (void)__close (fd);
        }
        return (0);
    }
    

    参考

    1. https://segmentfault.com/a/1190000008556669
  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    SIP协议
    PAT (Basic Level) Practice 1008 数组元素循环右移问题
    LeetCode-Algorithms 1. 两数之和
    PAT (Basic Level) Practice 1040 有几个PAT
    PAT (Basic Level) Practice 1023 组个最小数
    PAT (Basic Level) Practice 1021 个位数统计
    PAT (Basic Level) Practice 1007 素数对猜想
    PAT (Basic Level) Practice 1006 换个格式输出整数
    PAT (Basic Level) Practice 1004 成绩排名
  • 原文地址:https://www.cnblogs.com/suntus/p/15208240.html
Copyright © 2011-2022 走看看