本文章承接上一篇文章
一、控制终端的相关概念
一个会话可以有一个单独的
控制终端( controlling terminal)。这通常是终端设备(终端登录情况下)或伪终端设备(网络登录情况)
控制进程:建立与控制终端连接的会话首进程,被称之为控制进程( controlling process)一个会话中的几个进程组可被分成一个
前台进程组( foreground process group)以及一 个或几个
后台进程组(background process group)如果一个会话有一个控制终端,则它
有一个前台进程组,
其他进程组则为后台进程组无论何时键入
终端的中断键(常常是DELETE或Ctrl+C),都会将中断信号发送至
前台进程组的所有进程无论何时键入
终端的退出键(常常是Ctrl+\),都会将退出信号发送至
前台进程组的所有进程如果终端接口检测到调制解调器(或网络)已经断开连接,则将挂断信号送至控制进程(会话首进程)
以上的所有特征,如下图所示:
二、控制终端的分配
通常,我们不必担心控制终端,登录时,将自动建立控制终端
控制终端的分配:
系统如何分配一个控制终端依赖于具体实现。19.4节中将说明实际步骤当对话期首进程打开第一个尚未与一个会话相关联的终端设备时,只要在调用open时没有指定O_NOCTTY标志,System V派生的系统将此终止终端分配此会话当会话首进程用TIOCSCTTY作为request参数(第三个参数是空指针)调用ioctl时,基于BSD的系统会为会话分配控制终端。为使此调用成功执行,此会话不能已经有一个控制终端(通常 ioctl 调用紧跟在setsid调用之后,setsid保证此进程是一个没有控制终端的会话首进程)。除了以兼容模式支持其他系统以外,基于BSD的系统不使用POSIX.1中对open函数所说明的O_NOCTTY标志
三、/dev/tty文件
概念与功能:有时不管标准输入、标准输出是否重新定向,程序都要与控制终端交互作用。保证程序能与控制终端对话的方法是open文件/dev/tty。在内核中,此特殊文件是控制终端的同义语。自然,如果程序没有控制终端,则打开此设备将失败
使用案例
四、前、后台进程组获取与设置函数(tcgetpgrp、tcsetpgrp)
需要有一种方法来通知内核哪一个进程组是前台进程组,这样,终端设备驱动程序就能知道将终端输入和终端产生的信号送到何处
#include <unistd.h>
pid_t tcgetpgrp(int fd);
//返回值:成功返回前台进程组ID;出错返回-1
int tcsetpgrp(int fd, pid_t pgrpid);
//返回值:成功返回0;失败返回-1
大多数应用程序并不直接调用这两个函数。它们通常由作业控制shell调用
tcgetpgrp函数
功能:返回前台进程组ID,它与在fd上打开的终端相关联
tcsetpgrp函数
功能:如果进程有一个控制终端,则该进程可以调用tcsetpgrp将前台进程组ID设置为pgrpidpgrpid值应当是在同一会话中的一个进程组的ID。fd必须引用该对话期的控制终端
#include <termios.h>
pid_t tcgetsid(int fd);
//返回值:成功返回会话首进程的进程组ID;出错返回-1
给出控制TTY的文件描述符。通过tcgetsid函数,应用程序就能获得会话首进程的进程组ID需要管理控制终端的应用程序可以调用tcgetsid函数识别出控制终端的会话首进程的会话ID(它等价于会话首进程的进程组ID)