会话、进程组、线程组以及控制终端

  "会话/进程组/线程组"这几个概念呈层级关系,在Linux系统中,可以有多个会话,每个会话里面又可以包含多个进程组,每个进程组包含多个进程,每个进程构成一个线程组——一个线程组由一个进程内的一个线程或多个线程组成。

  会话是用户登录系统到退出系统前的全部活动,不同账户的登录属于不同会话,同一账户的多次登录也构成多个不同的会话。而进程组主要出于作业控制的目的,有些shell没有作业控制的能力,那么同一会话中只有一个进程组,所有的进程都属于这个进程组。

  每当用户登录到Unix主机的时候,系统将打开一个终端运行login程序等待用户输入用户名和密码,通过验证后则创建一个shell程序从该终端读取用户命令和输出显示信息,由该shell创建的所有进程都使用这个终端,即同一会话所有进程都使用相同终端。从登录成功到结束前创建的所有进程都属于这次会话(session),第一个被创建的进程(通常为shell)称为会话的领头进程(session leader),会话的领头进程的PID将作为该会话的会话ID(SID),而系统打开的那个终端就是这些进程的控制终端。进程打开/dev/tty可以获得当前进程的控制终端文件描述符号fd(没有控制终端的进程则会失败),用库函数tcgetsid(fd)可以获得会话ID(SID)。如可以用命令tty查看当前shell的控制终端,在字符界面的情况下,/dev/tty就是映射到/dev/tty1-6,在图形界面的情况下(Xwindows),/dev/tty映射到/dev/pts的伪终端上。

  在shell上的一条命令所产生的所有进程形成一个进程组,每个进程组内的第一个进程往往成为该进程组的领头进程(process leader),并以领头进程的PID作为组内进程的进程组ID(PGID)。进程组的生命周期持续到组中最后一个进程终止,或者加入其他进程组为止。可以利用getpgrp()系统调用来获取进程组ID。但是如果shell没有作业控制(job control)能力则不管理进程组,也就是所有进程构成一个进程组,例如ash中创建的进程都属于同一个会话、同一个进程组。

  看一个例子:

  

  &表示让进程在后台运行。完成登录的时候就创建了bash这个进程,所以bash自然而然作为整个会话的领头进程,bash的PID为3990,所有这次会话中所有进程的SID,我们可以看到,都是3990。第一条指令我们创建了top 、more两个进程,并且这两个进程都在后台执行,返回了[1]4001这个提示,从ps来看应该是返回了最后一个创建的后台进程的PID;然后我们执行ps j | more这条指令,又创建了两个进程ps 、more,这时候我们可以看到刚刚第一条指令创建的两个后台进程top和more,同属一个进程组,进程组的ID(PGID)为领头进程top的PID:4000,同样下面的两个前台进程ps、more也是同一个进程组,这个进程组的ID(PGID)为领头进程ps的PID:4002。用tty查看当前终端映射到了伪终端pts0。

posted @ 2017-04-09 17:04  Cccarl  阅读(843)  评论(0编辑  收藏  举报