历史部分,无聊可以跳过

历史部分,无聊可以跳过

在 Linux 中,终端与 Shell 相关联。终端将输入发送到 Shell(例如:pwd),而 Shell 将输出发送回终端(例如:/home/paul)。

下图展示了 Terminal 和 Shell 之间的关系(假设我使用的 Terminal 是gnome-terminal,Shell 是bash):

在此输入图像描述

现在我想知道的是终端和Shell使用什么机制来交换数据。这就是我认为发生的情况:

  • 执行时gnome-terminal,会在目录中创建一个代表串口的文件/dev/pts(假设文件名为/dev/pts/0)。
  • gnome-terminal然后将执行与其关联的 Shell(例如:bash),并向其传递 pts 文件名(例如,可以通过命令行参数传递 pts 文件名)。
  • 现在 和 都gnome-terminal将从bash开始读取/dev/pts/0
  • gnome-terminal要发送数据时bash,它会写入该数据/dev/pts/0,并bash从中读取该数据/dev/pts/0
  • bash要发送数据时gnome-terminal,它会写入该数据/dev/pts/0and gnome-terminal并从中读取该数据/dev/pts/0

该图显示了我刚刚解释的内容:

在此输入图像描述

我的理解正确吗?


笔记:当然,如果我们使用虚拟终端(即,当我们不使用 GUI 时),pts 文件可以是 tty 文件,但逻辑仍然是相同的。

答案1

你缺少了一个必要的部分。伪 tty 设备不像套接字那样对称。有主端和从端。中的文件/dev/pts代表从设备。

终端模拟器通过调用创建一个伪 tty openpty(或者对于您想要在新 tty 上运行新进程的常见情况加上一些额外的设置)forkptyopenpty在较低级别,这涉及打开/dev/ptmx并执行一些魔法 ioctl。

调用终端仿真器的结果是得到一对文件描述符,并且还可以得到slave对应的openpty文件名。/dev/pts主进程没有单独的名称,因为子进程不需要按名称打开它。

主设备和从设备的行为有点像套接字的两端:您在一端写入的内容将从另一端读取。但因为这是一个 tty,所以所有 tty 模式都会应用于途中的数据。

例如,如果您是终端仿真器,并且收到按键操作A,则应该写入'a'主文件描述符。这直接相当于通过串行线路从终端将该字节发送到计算机。它将导致'a'从从机读取(通过任何正在读取它的程序 - 例如 shell)。

D如果在按键按下时收到Ctrl按键按下,则应将一个4字节 ( 'D' ^ 0x40) 写入主文件描述符。 (因为这是真正的终端在线路上发送的内容。)接下来发生的情况取决于 tty 模式。在原始模式下,读取从属 tty 的程序将看到一个4字节。在cooked模式下,tty将激活“EOF特殊键按下”行为。

在相反的方向上,也有一些处理。当某些程序写入'\n'从属 tty 时,"\r\n"由于onlcr后处理,您可能会在主文件描述符上收到。

历史部分,无聊可以跳过

很久以前,从设备的名称如下/dev/ttyp0,每个设备都有一个相应的主设备,例如/dev/ptyp0。它们不是动态创建的。终端仿真器可以探测所有这些,找到当前未使用的一个,然后开始使用它。管理所有权和权限是一个问题。xtermsetuid-root 只是为了可以 chown 奴隶。

新方案称为“UNIX98 ptys”,通过神奇的 ioctl 处理设备创建和所有权,因此文件仅在/dev/pts使用时出现,并且由运行创建它们的程序的用户拥有。

相关内容