zoukankan      html  css  js  c++  java
  • Linux守护进程编写方法及原理

    什么守护进程?

    守护进程是运行在后台的一种用来提供服务的进程,他脱离控制台独立运行,守护进程是一种很有用的进 程。

    Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。

    守护进程的特征?

    1、后台运行
      守护进程最重要的特性是后台运行。脱离控制台,但我们关闭控制台是不能关闭守护进程的,可以使用kill -9 守护进程的PID 
    来强行关闭守护进程。
    2、独立于其运行前的环境
      守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。
    例如打开的文件描述符,因为我们的进程是直接继承了父进程,所以同样继承了父进程打开的文件,例如标准输入、输出、错误,当然这3个文件描述符最终是从init进程中继承而来的。
    3、启动方式
      守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由用户终端(通常是shell)执行。 
     

    进程间关系?

    (1)无关系
    (2)父子进程关系
    (3)进程组(group)由若干进程构成一个进程组。一个进程必定属于一个进程组,也只能
    属于一个进程组。 一个进程组中可以包含多个进程。 进程组的生命周期从被创建开始,
    到其内所有进程终止或离开该组,而且这个组存在与否与组长存在与否没有关系,也就是
    说,只要这个组中还有一个进程在运行,那么这个进程组就是存在的,而且就算是组长死
    了,那么组长不会变为还在运行的进程。

    提供进程组就是为了方便对进程进行管理。例如当我们要将一个进程组中的所有进程都关
    闭,那么就会一个一个依次关闭,但是这样是很麻烦的,并且必须要严格按照进程间父子
    兄弟关系顺序,否则会扰乱进程树。如果有了进程组之后,我们就可以调用命令以进程组
    ID(也就是组长的PID)为参数关闭所有的这个组中的进程。
    必须注意的是,只有当前进程不是进程组的组长时,才能创建一个新的会话。调用setsid
    之后,该进程成为新会话的会话组长,也是一个新的进程组组长。如果是进程组组长,那么

    调用这个是会失败的。

    (4)会话(session)会话就是进程组的组:一个或多个进程组的集合,其实就是可以认为
    是一个终端。

     

    守护进程的编写步骤:

    1:父进程fork创建子进程,父进程退出,子进程继续运行。

         int ret = fork();

         if (0 < ret)

             exit(0);     // 父进程直接退出 

       原因:因为我们要接下来要用setsid函数来脱离控制台,而前面说过,如果是进程组组长是不能调用setsid函数来开启新的会话的,

       而在shell下运行一个进程,那么这个进程就是一个新的进程组组长进程,所以我们就通过父进程fork创建子进程,而子进程虽然也是属于

       父进程这个进程组中,但是子进程并不是组长,所以是可以调用setsid函数来开启新的会话。

    2:子进程使用setsid创建新的会话期,脱离控制台。

       sid = setsid();

       if (-1 == sid)
      {
            perror("setsid error");
            exit(-1);
       }

    3:重新设定umask值

     进程从创建它的父进程那里继承了文件创建掩模,这可能会修改了守护进程所创建的文件的存取位。为防止这一点,按如下方法将文件创建掩模清除:

     umask(0);

    4:关闭打开的所有文件描述符

    进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们

    //关闭该进程打开的所有文件,以免由于该进程操作文件导致其他进程无法操作文件
    //首先要获取进程能够打开的最大的文件数
    int cnt = sysconf(_SC_OPEN_MAX);
    int i = 0;
    for (i = 0;i < cnt; i++)
    {
    close(i);
    }

    5:改变进程工作目录

    进程活动时,其工作目录所在的文件系统是不能卸下的。一般需要将工作目录改变到根目录/。意思就是如果我们的守护进程的工作目录在某个文件系统的目录下,那么

    将会导致这个文件系统无法被卸载。

    chdir("/");

    6:重定向标准输入、标准输出、标准错误

    open("/dev/null", O_RDWR);
    open("/dev/null", O_RDWR);
    open("/dev/null", O_RDWR);

  • 相关阅读:
    SpringBoot启动过程中,候选类的过滤和加载
    Dubbo发布过程中,扩展点的加载
    Dubbo发布过程中,服务发布的实现
    Dubbo发布过程中,服务端调用过程
    SpringBean加载过程中,循环依赖的问题(一)
    Dubbo发布过程中,消费者的初始化过程
    DiscuzQ构建/发布小程序与H5前端
    Delphi写COM+的心得体会
    DBGridEh导出Excel等格式文件
    数据库直接通过bcp导出xml文件
  • 原文地址:https://www.cnblogs.com/deng-tao/p/5993435.html
Copyright © 2011-2022 走看看