如何写好一个守护进程

int daemonize(int dump_core)
{
    int status;
    pid_t pid, sid;
    int fd; 

    pid = fork();
    if ((pid = fork()) == -1) {//means error occur
        fprintf(stderr, "fork failed:%s", strerror(errno));
        return -1; 
    }else if (pid > 0){//means this is the parent process, they can quit at once
        _exit(0);
    }   

    //means this is the child process
    /* 1st child continues and becomes the session leader */
    //fork twice to avoid zombie process
    sid = setsid();//creates a session and sets the process group ID
    if (sid < 0) {
        fprintf(stderr, "setsid() failed:%s", strerror(errno));
        return -1; 
    }   

    if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
        fprintf(stderr, "signal(SIGHUP, SIG_IGN) failed: %s", strerror(errno));
        return -1;
    }

    ///<use fork twice to avoid zombie process
    pid = fork();
    if ((pid = fork()) == -1) {//means error occur
        fprintf(stderr, "fork failed:%s", strerror(errno));
        return -1;
    }else if (pid > 0){//means this is the 1st child process, they can quit at once
        _exit(0);
    }

    /* 2nd child continues */
    /* change working directory */
    if (dump_core == 0) {
        status = chdir("/");
        if (status < 0) {
            fprintf(stderr, "chdir(\"/\") failed: %s", strerror(errno));
            return -1;
        }
    }

    /* clear file mode creation mask */
    umask(0);
    /* redirect stdin, stdout and stderr to "/dev/null" */
    fd = open("/dev/null", O_RDWR);
    if (fd < 0) {
        fprintf(stderr,"open(\"/dev/null\") failed: %s", strerror(errno));
        return NC_ERROR;
    }                                                                                                                                        

    status = dup2(fd, STDIN_FILENO);
    if (status < 0) {
        fprintf(stderr,"dup2(%d, STDIN) failed: %s", fd, strerror(errno));
        close(fd);
        return NC_ERROR;
    }
    status = dup2(fd, STDOUT_FILENO);
    if (status < 0) {
        fprintf(stderr,"dup2(%d, STDOUT) failed: %s", fd, strerror(errno));
        close(fd);
        return NC_ERROR;
    }

    status = dup2(fd, STDERR_FILENO);
    if (status < 0) {
        fprintf(stderr,"dup2(%d, STDERR) failed: %s", fd, strerror(errno));
        close(fd);
        return NC_ERROR;
    }

    if (fd > STDERR_FILENO) {
        status = close(fd);
        if (status < 0) {
            fprintf(stderr,"close(%d) failed: %s", fd, strerror(errno));
            return NC_ERROR;
        }
    }

    return NC_OK;
}


需要遵循几大原则:

  1. 设置mask,避免出现文件权限的问题
  2. fork两次,避免出现僵尸进程(父进程终止可以让shell结束退出)
  3. 使用set_id() 生成新的会话,并且将fork出的子进程作为groupid
  4. 重新设定工作目录
  5. 将标准输出重定向到/dev/null

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值