Linux:进程组/作业/会话

进程组

我们在利用指令查看进程信息的表头这里写图片描述
其中PPID与PID是父进程ID与子进程ID,而这里有个PGID是什么呢?
我们在谈论线程的时候,说过线程有一个线程组,而线程组ID就是这个线程主线程的ID。也是这个线程所组成进程的进程PID。而进程也是有进程组的,这里的这个PGID就是进程组ID,每个进程组有唯一的一个进程组ID。并且这个ID就是进程组组长ID,也就是创建进程组的进程。类似于线程里面的主线程与线程组的关系。但是不同之处在于,线程组里面某一个线程异常退出(注意是异常退出)整个线程组就会终止。而进程组内某一个进程异常退出不会影响到进程组。并且线程组内主线程退出,线程组也随之消失。而进程组的组长退出,进程组仍旧存在。直至进程组内部最后一个进程退出,进程组才消失。

#include <stdio.h>
#include <unistd.h>

int main()
{
  pid_t pid1,pid2,pid3;

  pid1 = fork();
  pid2 = fork();
  pid3 = fork();
  while(1);

  return 0;
}

这里写图片描述
我们运行以后查看此时进程,然后,我们杀掉进程组长。这个时候组长退出。由于接下来三个进程时组长创建的,所以组长是后面三个进程的父进程,父进程退出,子进程为孤儿进程,被一号进程收养。所以这三个进程的PPID为1。我们发现在组长退出后,进程组还存在。

注:
ps指令的选项:
a:不仅列当前用户的进程,也列出所有其他用户的进程
x:不仅列有控制终端的进程,也列出所有无控制终端的进
j :列出与作业控制相关的信息

作业

我们常常说前台进程后台进程,其实这里面并不是前台进程后台进程。 这里更应该说的是前台进程组,后台进程组。而我们又称之为作业。一个前台作业可以由多个进程组组成,一个后台作业也可由由多个进程组组成。但是我们在终端下,只能运行一个前台作业,和任意个后台作业。这样看来,作业与进程组有些相似,不过二者还是有区别的。如果作业中某个进程由创建了子进程,那么这个时候子进程并不属于这个作业。也就是说作业在一个可执行文件从文件到进程组的这个过程中,已经创建完毕。我们在打开终端的时候Shell就是我们的前台作业,我们可以通过给Shell发送指令,Shell解析指令后传给操作系统内核,这样达到了对操作系统的控制。

在作业当中的进程,如果创建了子进程,这个子进程是此时进程组内的成员,但是它并不是作业当中的成员。

#include <stdio.h>
#include <unistd.h>

int main()
{
  pid_t pid = fork();
  if(pid < 0) {
    printf("fork error!\n");
    return -1;
  } else if(pid == 0) {
    while(1) {
      printf("i am child,my pid is %d\n",getpid());
      sleep(1);
    }
  } else {
    int i = 5;
    while(i) {
      printf("i am child,my pid is %d\n",getpid());
      sleep(1);
      i--;
    }
  }

  return 0;
}

这里写图片描述
我们发现,父进程退出以后,子进程仍在运行,但是我们输入指令kill -9 加子进程pid,这时候成功杀掉了子进程。也就是说现在,我们的Shell是起作用的。这是因为我们打开终端,此时前台作业是Shell,然后当我们敲下./job的时候,此时Shell无法运行,因为前台只允许一个作业。这个时候job成了一个新的作业。而这个瞬间,job并没有子进程的创建。也就是说将来创建的子进程并不属于这个作业。此时的前台作业就是job,当job创建子进程后,由于前台只允许有一个作业,所以此时的子进程就属于后台作业。而当job退出以后,Shell被提到前台作为前台作业,这个时候子进程仍旧在后台工作,为后台作业,但是后台作业可以向标准输出缓冲区进行输入。所以就出现了屏幕不断打印内容。这时候由于我们的Shell已经成前台作业了,所以就可以进行命令解析。我们输入kill -9就可以杀掉这个后台作业。

我们可以用指令jobs查看当前有哪些作业,其中fg命令可以将后台作业提到前台运行,bg可以将前台作业放到后台。前台放到后台时,首先用ctrl + z将作业暂停,再进行放置。

会话(Session)

我们在最开始的那一栏里,可以看到有一个表头SID,其实这个SID就是会话ID。会话是一个或多个进程组的集合。一个会话可以有一个控制终端。一般情况下,这个控制终端是登录到其上的终端设备。一个会话应该包括控制进程(话首进程),一个前台进程组和多个后台进程组。
我们来做个测试,我们先打开我们的Xshell,连接上我们的虚拟机,现在相当于我们打开了一个终端。然后我们运行任意进程。查看进程的会话ID。
这里写图片描述
我们发现,在我们的进test运行的时候,它的会话ID是25467,而我们查看25467的时候发现,这个会话ID恰好是bash的进程ID,也就是说,我们这个终端的话首进程就是bash,而bash不仅创建会话,还创建进程组。
我们现在做个测试,我们将我们的bash进程kill掉,也就是说关闭话首进程。看看有什么后果。
这里写图片描述

这个测验就让我们知道了,一个会话当中,如果话首进程退出,那么会话退出。


欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值