守护进程详解

基本概念

一种长期运行的进程:这种进程在后台运行,并且不跟任何的控制终端关联

特点

  • 生存期长[不是必须,但一般应该这样做],一般是操作系统启动的时候他就启动,操作系统关闭的时候他才关闭
  • 守护进程跟终端无关联,也就是说他们没有控制终端,所以你控制终端退出,也不会导致守护进程退出
  • 守护进程是在后台运行,不会占着终端,终端可以执行其他命令

Linux 常见守护进程

  • ppid = 0:内核进程,跟随系统启动而启动,声明周期贯穿整个系统
  • 内核守护进程:cmd列名字带[]这种
  • init:也是系统守护进程
  • 用户级守护进程:cmd列中名字不带[]的普通守护进程

共同点:

  • 大多数守护进程都是以超级用户特权运行的
  • 守护进程没有控制终端,TT这列显示? 其中,内核守护进程以无控制终端方式启动,普通守护进程可能是守护进程调用了setsid的结果(无控制端)

实现方式

  1. 调用umask(0),其用来限制(屏蔽)一些文件权限的
  2. fork()一个子进程(脱离终端)出来,然后父进程退出(把终端空出来,不让终端卡住)。以此来调用setsid(),子进程有单独的sid;而且子进程也成为了一个新进程组的组长进程;同时,子进程不关联任何终端了
  3. 输入输出重定向到/dev/null
//创建守护进程
//创建成功则返回1,否则返回-1
int ngx_daemon()
{
    int  fd;

    switch (fork())  //fork()子进程
    {
    case -1:
        //创建子进程失败,这里可以写日志......
        return -1;
    case 0:
        //子进程,走到这里,直接break;
        break;
    default:
        //父进程,直接退出 
        exit(0);         
    }

    //只有子进程流程才能走到这里
    if (setsid() == -1)  //脱离终端,终端关闭,将跟此子进程无关
    {
        //记录错误日志......
        return -1;
    }
    umask(0); //设置为0,不要让它来限制文件权限,以免引起混乱

    fd = open("/dev/null", O_RDWR); //打开黑洞设备,以读写方式打开
    if (fd == -1) 
    {
        //记录错误日志......
        return -1;
    }
    // dup2用来复制参数oldfd所指的文件描述符。当复制成功是,返回最小的尚未被使用过的文件描述符,若有错误则返回-1
    if (dup2(fd, STDIN_FILENO) == -1) //先关闭STDIN_FILENO[这是规矩,已经打开的描述符,动他之前,先close],类似于指针指向null,让/dev/null成为标准输入;
    {
        //记录错误日志......
        return -1;
    }

    if (dup2(fd, STDOUT_FILENO) == -1) //先关闭STDIN_FILENO,类似于指针指向null,让/dev/null成为标准输出;
    {
        //记录错误日志......
        return -1;
    }

     if (fd > STDERR_FILENO)  //fd应该是3,这个应该成立
     {
        if (close(fd) == -1)  //释放资源这样这个文件描述符就可以被复用;不然这个数字【文件描述符】会被一直占着;
        {
            //记录错误日志......
            return -1;
        }
    }

    return 1;
}

注意事项

  1. 守护进程不会收到来自内核的SIGINT(ctrl+C),SIGWINCH(终端窗口大小改变) 信号,故可以用来做reload操作
posted @ 2021-08-08 20:00  Karsonn  阅读(495)  评论(0)    收藏  举报