zoukankan      html  css  js  c++  java
  • 守护进程的编写

    守护进程的编写

    ps: 参考资料:linux C++通讯架构实战 卷1

    一,普通进程

    查看进程

    ps -eo pid,ppid,sid,tty,pgrp,comm,stat,cmd | grep -E 'bash|PID|nginx'
    
    • 这种进程都有各自对应的终端,终端退出,该进程也就退出,它的父进程是一个bash
    • 终端被占用,你输入命令没有作用
    • 如果放到后台(bg), 输入命令有用了,但是终端关闭进程仍然会退出

    二,守护进程

    定义:一种长期在后台运行的进程,不与任何终端关联

    • Linux本身是有很多守护进程默默运行着。查看ps -efj
      • ppid = 0 内核进程,跟随系统,生命周期贯穿这个系统。
      • cmd 带 [ ] 的是内核守护进程
      • 老祖init,也是系统守护进程,它负责启动各运行层次特定的系统服务;所以很多进程的PPID是init。而且这个init也负责收养孤儿进程;
      • cmd列中名字不带[]的普通守护进程(用户级守护进程)
    • 共同特点
      • 大多数守护进程都是以超级 用户特权运行的;
      • 守护进程没有控制终端,TT这列显示?
      • 内核守护进程以无控制终端方式启动
      • 普通守护进程可能是守护进程调用了setsid的结果(无控制端);

    编写规则

    • 调用umask(0);
      • umask是个函数,用来限制(屏蔽)一些文件权限的。
    • fork()一个子进程(脱离终端)出来,然后父进程退出( 把终端空出来,不让终端卡住);固定套路
      • fork()的目的是想成功调用setsid()来建立新会话,目的是子进程有单独的sid;
      • 而且子进程也成为了一个新进程组的组长进程;同时,子进程不关联任何终端了;

    在编写前还需要知道一些相关概念

    • 文件描述符
      • 当你打开一个存在的文件或者创建一个新文件,操作系统都会返回这个文件描述符(其实就是代表这个文件的),后续对这个文件的操作的一些函数,都会用到这个文件描述符作为参数;
      • linux中三个特殊的文件描述符,数字分别为0,1,2
        • 0:标准输入【键盘】,对应的符号常量叫STDIN_FILENO
        • 1:标准输出【屏幕】,对应的符号常量叫STDOUT_FILENO
        • 2:标准错误【屏幕】,对应的符号常量叫STDERR_FILENO
      • 类Unix操作系统,默认从STDIN_FILENO读数据,向STDOUT_FILENO来写数据,向STDERR_FILENO来写错误;
      • 万物皆文件
      • 你程序一旦运行起来,这三个文件描述符0,1,2会被自动打开(自动指向对应的设备);
    //文件描述符虽然是数字,但是,如果我们把文件描述符直接理解成指针(指针里边保存的是
    //地址——地址说白了也是个数字);
    write(STDOUT_FILENO,"aaaabbb",6);
    
    • 输入输出重定向
      • 以前老写的freopen应该是同一个原理。
      • 在Linux命令行中的 > < 可以重定向输出
    • 空设备 【 /dev/null 】
      • 一个特殊的文件设备,重定向过去的东西都会被吸收(黑洞)

    • 守护进程不会收到的信号:内核发给你,另外的进程发给你的

      • SIGHUP信号
        • 守护进程不会收到来自内核的 SIGHUP 信号; 潜台词就是 如果守护进程收到了 SIGHUP信号,那么肯定是另外的进程发给你的;
        • 很多守护进程把这个信号作为通知信号,表示配置文件已经发生改动,守护进程应该重新读入其配置文件;
      • SIGINT、SIGWINCH信号
        • 守护进程不会收到来自内核的 SIGINT(ctrl+C),SIGWINCH(终端窗口大小改变) 信号;
    • 守护进程和后台进程的区别

      • 守护进程和终端不挂钩;后台进程能往终端上输出东西(和终端挂钩);
      • 守护进程关闭终端时不受影响,守护进程会随着终端的退出而退出;

    案例代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    //创建守护进程
    //创建成功则返回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;
        }
        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;
    }
    
    int main(int argc, char *const *argv)
    {
        if(ngx_daemon() != 1)
        {
            //创建守护进程失败,可以做失败后的处理比如写日志等等
            return 1; 
        } 
        else
        {
            //创建守护进程成功,执行守护进程中要干的活
            for(;;)
            {        
                sleep(1); //休息1秒
                printf("休息1秒,进程id=%d!
    ",getpid()); //你就算打印也没用,现在标准输出指向黑洞(/dev/null),打印不出任何结果【不显示任何结果】
            }
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    java面试笔记6
    Java面试笔记5
    Java面试笔记5
    网上订单管理-新增
    网上订单管理-级联;可编辑列表
    网上订单管理-新增、修改
    数据库嵌套查询
    网上订单管理-数据呈现
    video 移动端内联播放,视频上层可显示弹幕、点赞。video转canvas播放
    vue 日期格式化过滤器
  • 原文地址:https://www.cnblogs.com/Q1143316492/p/10745712.html
Copyright © 2011-2022 走看看