so true

心怀未来,开创未来!
随笔 - 160, 文章 - 0, 评论 - 40, 引用 - 0
数据加载中……

daemonize

#include <sys/param.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
void daemonize() {
    int pid = -1, fd = -1;
    // 1.转变为后台进程
    if ((pid = fork()) == -1) exit(1);
    if (pid != 0) exit(0); // 父进程(前台进程)退出
    // 2.离开原先的进程组,会话
    if (setsid() == -1) exit(1); // 开启一个新会话
    // 3.禁止再次打开控制终端
    if ((pid = fork()) == -1) exit(1);
    if (pid != 0) exit(0); // 父进程(会话领头进程)退出
    // 4.关闭打开的文件描述符,避免浪费系统资源
    for (int i = 0; i < NOFILE; i++)
        close(i);
    // 5.改变当前的工作目录,避免卸载不了文件系统
    if (chdir("/") == -1) exit(1);
    // 6.重设文件掩码,防止某些属性被父进程屏蔽,也有设置为0027的(守护进程创建的临时文件不希望被其他用户查看)
    umask(0);
    // 7.重定向标准输入,输出,错误流,因为守护进程没有控制终端
    // 如果只是把0、1、2都close了,那么守护进程里新创建的文件fd会用到0、1、2,如果用户的代码里有用到printf/cout之类的,那就会把数据打到新创建的文件中,这样就会产生混淆
    if ((fd = open("/dev/null", O_RDWR)) == -1) exit(1); // 打开一个指向/dev/null的文件描述符
    dup2(fd, STDIN_FILENO);
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);
    close(fd);
    // 8.本守护进程的子进程若不需要返回信息,那么交给init进程回收,避免产生僵尸进程,否则子进程退出后将成为僵尸进程
    if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) exit(1);
}

对setsid阐述较透彻:http://www.cnblogs.com/xuxm2007/archive/2011/07/29/2121280.html
对终端的事说了些:http://blog.51cto.com/10541559/1771212
对syslog的事说了些:https://www.linuxidc.com/Linux/2015-01/111933.htm
此外,man 3 daemon这个库函数只实现了部分阶段(例如没有屏蔽SIGCHLD以及对mask做任何处理):https://github.com/lattera/glibc/blob/master/misc/daemon.c

posted on 2018-04-12 18:36 so true 阅读(157) 评论(0)  编辑  收藏 所属分类: Linux


只有注册用户登录后才能发表评论。


网站导航: