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
  • 相关阅读:
    python库--pandas--Series.str--字符串处理
    前端--jstree--异步加载数据
    python库--flask--创建嵌套蓝图
    Git--生成公钥和私钥并添加gitlab访问权限
    es查询--请求body
    python生成时间序列(date_range)
    golang使用组合完成伪继承
    golang interface类型的动态绑定
    ruby环境安装草稿
    openfire
  • 原文地址:https://www.cnblogs.com/suntus/p/15208240.html
Copyright © 2011-2022 走看看