1. 控制终端
一般来说,在 bash 中运行的进程,都会伴随着一个控制终端。默认情况下(没有重定向),每个进程的标准输入、标准输出和标准错误输出都指向控制终端。
需要特别注意的是,控制终端是进程的属性,它保存在进程 PCB 中。而 bash 进程在启动的时候,会自动建立一个控制终端。所以由 bash 进程启动(fork)的进程都会继承控制终端。所以在同一个会话中,控制终端都是一样的。
进程可以没有控制终端。如果要想让进程脱离控制终端,可以让该进程创建新的会话(如果你忘记了,请查看前面的会话相关的文章)。
2. 控制进程
建立与控制终端连接的会话首进程(session leader),被称为控制进程。如果终端设备与控制终端断开连接,系统会发送信号给控制进程。
如果会话首进程终止,则该信号发送到该会话前台进程组(见第 3 节)。一个进程退出导致一个孤儿进程组(详见《孤独进程与孤独进程组》)产生时,如果任意一个孤儿进程组中的进程处于 STOP 状态,发送 SIGHUP 和 SIGCONT 信号到该进程组中所有进程。
3. 前台进程组与后台进程组
如果一个会话有控制终端,则它有一个前台进程组,以及多个后台进程组。使用命令 ps ajx
可以查看会话的前台进程组,位于 TPGID 一栏,如果该值为 -1,表示该进程没有控制终端,所以也没有前台进程组。
当在终端输入或者终端产生信号时,都会发送到前台进程组。在很久以前学习信号时,我们使用快捷键 CTRL C、CTRL Z 等等发送信号,并没有指定进程和进程组编号,实际上,这样产生的信号默认都是发送到前台进程组中去的。
当你执行 CTRL C 时,前台进程组中所有的进程都会中断。
下面两个函数是用来获取和设置当前会话中的前台进程组的:
4. 实验
执行下面的命令:
再另一个终端中执行:
结果如图 1 所示。
图1 控制终端,前台进程组,后台进程组
从图 1 中可以看到会话 6465 的前台进程组 id 号是 7007. 该会话中的其它进程组都是后台进程组。
上面的例子抽象出来如图 2 所示。
图2 前台进程组,后台进程组,控制进程
5. 总结
- 理解控制终端
- 知道什么是前台进程组和后台进程组