- 进程组和会话在进程之间形成了一种两级层次关系:
- 进程组是一组相关进程的集合
- 会话是一组相关进程的集合
- 进程组和会话是为支持shell作业控制而定义的抽象概念,用户通过shell能够交互式地在前台或者后台运行命令。术语“作业”通常与术语“进程组”作为同义词来看待。
进程组由一个或者多个共享进程组标识符PGID的进程组成。
- 进程组ID是一个数字,其类型为进程ID一样(pid_t)
- 一个进程组拥有一个进程组首进程,该进程是创建该组的进程,其进程ID是该进程组的ID。
- 新进程会继承其父进程所属的进程组ID
进程组拥有一个生命周期:
- 其开始时间为首进程创建组的时刻,结束时间为最后一个成员进程退出组的时刻
- 一个进程可能会因为终止而退出进程组,也可能因为加入了另外一个进程组而退出进程组
- 进程组首进程无需是最后一个离开该进程组的成员
会话是一组进程组的集合:
- 进程的会话成员关系是由会话标识符SID确定的,其类型也是pid_t
- 会话首进程是创建该新会话的进程,其进程 ID 会成为会话 ID
- 新进程会继承其父进程的会话 ID
一个会话中的所有进程共享单个控制终端。控制终端会在会话首进程首次打开一个终端设备时被建立。一个终端最多可能会称为一个会话的控制终端
在任一时刻,会话中的其中一个进程组会称为终端的前台进程组,其他进程组会称为后台进程组,只有前台进程组中的进程才能从控制终端中输入。当用户在控制终端中输入其中一个信号生成终端字符之后,该信号会被发送到前台进程组中的所有成员。这些字符包括生成 SIGINT 的中断字符(通常是 Control-C)、生成 SIGQUIT 的退出字符(通常是 Control-\)、生成 SIGSTP 的挂起字符(通常是 Control-Z)
当到控制终端的连接建立起来(即打开)之后,会话首进程会成为该终端的控制进程。成为控制进程的主要标志是当断开与终端之间的连接时内核会向该进程发送一个SIGHUP 信号。
通过检查 Linux 特有的/proc/PID/stat 文件,就能确定任意进程的进程组 ID 和会话 ID。此外,还能确定进程的控制终端的设备 ID(一个十进制数字,包含主 ID 和辅 ID)和控制该终端的控制进程的进程 ID。更多细节信息请参考 proc(5)手册
会话和进程组的主要用途是用于shell作业控制。举个例子,对于交互式登录来讲,
- 控制终端是用户登录的途径
- 登录shell是会话首进程和终端的控制进程,也是其自身进程组的唯一成员
- 从shell中发出的每个命令或者通过管道连接的一组命令都会导致一个或者多个进程的创建,并且shell会把所有这些进程都放在一个新进程组中(这些进程在一开始是其进程组中的唯一成员,它们创建的所有子进程会称为该组中的成员)
- 当命令或以管道连接的一组命令以&符号结束时会在后台进程组中运行这些命令,否则就会在前台进程组中运行这些命令
- 在登录会话中创建的所有进程都会成为该会话的一部分。
在窗口环境中,控制终端是一个伪终端。每个终端窗口都有一个独立的会话,窗口的
启动 shell 是会话首进程和终端的控制进程
下图给出了执行下面的命令之后各个进程之间的进程组和会话关系