美文网首页
3.7、守护进程详解、范例演示

3.7、守护进程详解、范例演示

作者: 奥斯特洛司机 | 来源:发表于2019-04-01 20:08 被阅读0次

    1、普通进程运行观察
    进程有对应的终端,终端退出,那么该进程也就消失了。父进程是bash。
    终端被占用。
    2、守护进程基本概念
    守护进程是一种长期运行的进程,在后台运行,不跟任何终端关联。
    基本特点:生存周期比较长,一般是操作系统启动的时候启动,
    操作系统关闭的时候才关闭。
    守护进程跟终端无关联,没有控制终端。不随终端退出而退出。
    守护进程在后台运行。
    linux操作系统本身有很多守护进程在默默运行,维持着系统的日常活动,30-50个。
    ppid = 0的属于内核进程,跟随系统启动而启动,生命周期贯穿整个系统。
    比如:init,kthreadd
    cmd列名字带【】的就是内核守护进程。
    init:也是系统守护进程,负责启动各运行层次特定的系统服务。
    所以很多进程的ppid是init。。也负责收养孤儿进程。
    cmd列中不带【】的是普通守护进程(用户守护进程)
    共同点总结:大多数守护进程都是以超级用户权限运行的;
    守护进程没有控制终端,TT这列显示?
    a、内核守护进程以无控制终端方式启动
    b、普通守护进程可能是守护进程调用了setsid的结果(无控制终端)。

      守护进程虽然可以从终端启动,但和终端不挂钩。守护进程实在后台爱运行,不应该从键盘上接收任何东西。也不应该把输出结果打印大终端上来。所以要把守护进程的标准输入、标准输出重定向到空设备。
    

    3、守护进程编写规则
    a、调用umask(0):用来限制(屏蔽)一些文件权限的。
    b、fork一个子进程出来,然后父进程退出,把控制终端空出来,
    fork的目的是想成功调用setsid()来建立新会话。
    目的是让子进程有单独的sid,而且子进程也成为新进程组的组长进程,
    同时不关联任何终端了。
    c、把守护进程的标准输入、标准输出重定向到空设备。从而确保不从键盘接收,
    不打印到屏幕。
    int fd;
    fd = open("/dev/null" ,O_RDWR);
    dup2(fd, STDIN_FILENO); //复制文件描述符,类似指针赋值,
    标准输入指向黑洞。
    dup2(fd, STDOUT_FILENO);
    if(fd > STDERR_FILENO)
    close(fd); //等价于fd = NULL
    3.1、文件描述符
    正数,用来标识一个文件。当你打开一个存在的文件,
    或者创建一个新文件,操作系统都会返回这个文件描述符。
    后续对文件操作的一些函数,都会调用到这个文件描述符作为参数。

              三个特殊的文件描述符:0(标准输入),1(标准输出),2(标准出错)
              分别对应的符号常量:STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO
              类Unix默认从STDIN_FILENO读数据,从STDOUT_FILENO写数据。
              一切皆文件。所以以上都看成文件。
              程序启动,自动打开。
       3.2、输入输出重定向
               输出重定向:1>/dev/null
       3.3、空设备
                /dev/null,是一个特殊的设备文件,丢弃写入。
       3.4、实现范例,nginx提炼出来可用于商业用途
    
    |#include  <sys/stat.h>
    |#include <fcntl.h>
    
    //创建守护进程
    int ngx_daemon()
    {
         int fd;
         switch(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
              //记录错误日志
              return -1;
         }
         if(dup2(fd, STDOUT_FILENO) == -1){   //输出重定向到/dev/null
              //记录错误日志
              return -1;
         }
         if(fd > STDERR_FILENO){
              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);
                printf("休息1秒,进程id = %d\n", getpid()); //此处打印无效果,标准输出已重定向到/dev/null
            }
        }
        return 0;
    }
    
    

    Ss :小s表示进程leader
    nginx的master进程也是守护进程,这个进程就是抄自nginx。
    守护进程可以用命令启动,如果想开机启动,要系统初始化脚本启动。

    4、守护进程不会收到的信号
    4.1、SIGHUP信号
    守护进程不会受到来自内核发送的信号。
    另外的进程可以发SIGHUP信号,
    作为通知信号,表示配置文件已经发生改动,守护进程应该重新读入。
    sudo ./nginx -s reload 给已经启动的老master发送SIGHUP信号,
    使用新配置启动新worker进程
    跟kill -1 pid效果一样。 (看nginx源码)
    4.2、SIGINT、SIGWINCH信号(来自内核发送的)
    Ctrl+C,SIGWINCH(终端窗口大小改变信号)
    具体用来干嘛?

    5、守护进程和后台进程的区别
    守护进程和终端无挂钩,但是后台进程是挂钩的,能往终端输出东西。
    守护进程关闭终端不受影响,后台进程就会跟着退出。
    脱离终端,不会屏蔽文件权限。

    相关文章

      网友评论

          本文标题:3.7、守护进程详解、范例演示

          本文链接:https://www.haomeiwen.com/subject/usvvbqtx.html