LinuxC进程组、会话、守护进程

1.进程组
  定义:进程的集合,进程组ID等于组长进程ID。类似于QQ群号等于群主QQ号。
  生命周期:进程组里的最后一个进程离开的时候,进程组生命周期结束,也就是说只要有进程,该进程组就存在。
  作用:简化对多个进程的管理。
  函数:getpgrp()、getpgid()、setpgid()
  进程组组长:创建这个进程组的进程,简称为该进程组组长(组长进程)。该进程组ID等于该进程ID。子进程进程组ID默认等于父进程进程组ID。
2.会话
  定义:进程组的集合。非组长进程调用setsid函数创建一个会话,这个会话ID等于该进程ID,该进程的进程组也变为该进程ID,也就是该进程的会话ID==该进程的进程组ID==该进程ID。
  注意:组长进程不能创建会话。因为一个进程创建会话后,该进程的进程组也变了,所以和"进程组ID等于组长进程ID"这句话就矛盾了。
  特点:新会话会脱离原有的控制终端,所以会话没有控制终端。所以创建新会话是守护进程的关键一步。创建会话需要root权限(ubuntu除外不需要)。
  函数:getsid()、setsid()、命令行输入ps -ajx 可查看与会话相关的进行信息
3.守护进程
  定义:也称为精灵进程(daemond)。是一些后台服务进程,没有控制终端,不与用户直接交互,不受用户登陆注销的影响,一直运行着。比如sshd服务、ftpd服务等都是守护进程。
  注意:创建守护进程,最关键的是调用setsid创建新的会话,成为该会话首进程。
  创建守护进程步骤:
    1)调用fork()创建子进程,非组长进程
    2)调用setsid()创建新会话,脱离终端
    3)调用chdir()改变工作目录,防止占用可卸载的文件系统
    4)调用umask()重置文件权限掩码,防止继承父进程的文件屏蔽字拒绝某些权限
    5)调用close()关闭打开的继承父进程的无用文件描述符
  示例代码:

    void test_daemond()
    {
    //1.fork()子进程
    //2.sid()新建新会话,脱离终端
    //3.chdir()切换工作目录,防止占用可卸载的文件系统
    //4.umask(0)重置文件权限掩码,防止继承父进程的文件屏蔽字拒绝某些权限
    //5.close(fd)关闭打开的继承父进程的无用文件描述符
      pid_t pid = fork();//1.创建子进程,父进程退出
      if (pid < 0)
      {
        perror("fork error");
        exit(EXIT_FAILURE);
      }
      if (pid > 0)
      {//parent
        exit(EXIT_SUCCESS);
      }
      if (setsid() == -1)
      {//2.创建新会话,脱离终端
        perror("setsid error");
      }
      if (chdir("/") == -1)
      {//3.切换工作目录,不一定是根目录哈
        perror("chdir error");
      }
      printf("old umask:%d\n", umask(0));//4.重置文件掩码

      //5.关闭标准输入输出错误流
      close(STDIN_FILENO);//fd=0,先关闭fd=0
      open("/dev/null", O_RDWR);//再打开该文件,根据最小fd可用原则,所以/dev/null对应的fd为0
      dup2(STDIN_FILENO, STDOUT_FILENO);//将fd=1重定向到fd=0,并关闭fd=1
      dup2(STDIN_FILENO, STDERR_FILENO);//将fd=2重定向到fd=0,并关闭fd=2
      while (1)
      {
        sleep(1);
        printf("daemond working...\n");
      }
    }

猜你喜欢

转载自www.cnblogs.com/yongfengnice/p/11961052.html