/dev/pts 文件中存储了什么,我们可以打开它们吗?

use*_*323 91 linux terminal devices pty

据我所知,/dev/pts文件是为 ssh 或 telnet 会话创建的。

Gil*_*il' 138

中没有存储任何内容/dev/pts。这个文件系统纯粹存在于内存中。

中的条目/dev/pts伪终端(简称 pty)。Unix 内核有一个通用的终端概念。终端为应用程序提供了一种通过终端设备显示输出和接收输入的方法。一个进程可能有一个控制终端——对于文本模式的应用程序,这就是它与用户交互的方式。

终端可以是硬件终端(“tty”,“电传打字机”的缩写)或伪终端(“pty”)。硬件终端通过一些接口连接,例如串行端口 ( ttyS0, …) 或 USB ( ttyUSB0, …) 或通过 PC 屏幕和键盘 ( tty1, …)。伪终端由终端仿真器提供,它是一个应用程序。一些类型的伪终端是:

  • GUI 应用程序,例如 xterm、gnome-terminal、konsole ……将键盘和鼠标事件转换为文本输入并以某种字体以图形方式显示输出。
  • 多路复用器应用程序,例如 screen 和 tmux 中继输入和输出到另一个终端,以将文本模式应用程序与实际终端分离。
  • 远程 shell 应用程序,例如 sshd、telnetd、rlogind……在客户端的远程终端和服务器上的 pty 之间中继输入和输出。

如果程序打开终端进行写入,则该程序的输出会出现在终端上。多个程序同时输出到一个终端是很常见的,尽管这有时会令人困惑,因为无法分辨输出的哪一部分来自哪个程序。尝试写入其控制终端的后台进程可能会被SIGTTOU 信号自动挂起

如果程序打开终端进行读取,则来自用户的输入将传递给该程序。如果多个程序从同一个终端读取,每个字符将独立路由到其中一个程序;不推荐这样做。通常,在给定时间只有一个程序主动从终端读取;试图虽然它们不是在从他们的控制终端读出的程序的前景通过一个SIGTTIN信号自动暂停

要进行实验,请tty在终端中运行以查看终端设备是什么。让我们说它是/dev/pts/42。在另一个终端的 shell 中,运行echo hello >/dev/pts/42:字符串hello将显示在另一个终端上。现在运行cat /dev/pts/42并输入另一个终端。要cat终止该命令(这将使另一个终端难以使用),请按Ctrl+ C

写入另一个终端有时对于显示通知很有用;例如write命令就是这样做的。通常不会从另一个终端读取。

  • @Patrick 后台进程写入终端得到 SIGTTOU,这是一个错字。多个程序*可以*同时从终端读取(试试看,我在下一段中描述的方式;您必须从控制终端不是该终端的进程中执行此操作)。是的,你可以从另一个终端读取,只要它属于你——为什么你认为这是不可能的? (5认同)
  • @Patrick 当然,`read` 调用只会返回连续的字符(或者更确切地说是字节,我应该说),但是应用程序无法控制 `read` 调用将返回多少字节,所以也没有更好的。 (2认同)

Bru*_*ger 21

中的文件/dev/pts是“伪 ttys”。它们在某种程度上就像命名管道,但它们也模仿旧的串行连接终端,如 VT-100。伪 ttys 负责将字节从键盘传输到程序,从程序传输到输出设备,这听起来很简单。但这回答了您的明确问题:/dev/pts/0例如,内核不存储任何内容。只有来自连接到伪 tty 的程序的 stdout 的字节流进入,并且其 stdin 连接到相同伪 tty 的程序读取这些字节。

伪 ttys 还在这些字节流中放置了一个间接层。内核可以检查字节中的特殊值,例如“Control-C”或“Control-D”或“Control-U”(它们都是可配置的,请参阅man stty参考资料)并发送 SIGINT、在 stdin 上设置文件结尾或擦除输入上的一行。某处还有一个缓冲功能,所以我的“什么都不存储”有点错误,但只有几千字节。

内核可以检查输出的字节值,并执行诸如将换行符(ASCII 换行符、LF 或"\n")转换为两个字节、回车和换行符(CRLF 或"\r\n")或串行终端硬件需要的任何字节等操作。伪 tty 的间接性允许独立于硬件。

伪 ttys 还允许所有“设置波特率”、“设置奇偶校验”等ioctl()系统调用,并且可能对它们没有任何作用。这使得在 VT-100、ADM-3 和 Wyse 之类的时代编写的程序可以继续运行而不会出错。软件,即伪 ttys 设备驱动程序,就像硬件一样工作。

sshd和可以使用伪 tty telnet,但它们也用于终端仿真器(如xtermrxvt)和通常在 xterm 内运行的外壳之间。

Linux 和许多 Unix 都有伪 tty。计划 9 没有。伪 ttys 是一点点遗迹,是从串行电缆连接的硬件终端时代遗留下来的。


gol*_*cks 16

/dev/是设备文件的特殊目录。这些是抽象的,它们不是磁盘上的真实文件。该目录在引导时填充,并且可能会更改以反映现有设备接口,这些接口由内核和用户空间守护进程创建和销毁udevd

如此表示的许多设备都是虚拟的。这包括 中的条目/dev/pts,它们是控制台设备。这就是为远程会话创建一个的原因;它们也会在您打开本地 GUI 终端时创建。

您可以将它们作为文件打开,尽管它没有太大的使用价值。要获取/dev/ptsshell 连接的节点,请使用tty

> tty
/dev/pts/4
Run Code Online (Sandbox Code Playgroud)

现在切换到其他控制台并尝试:

> echo "duck!" > /dev/pts/4
Run Code Online (Sandbox Code Playgroud)

聪明的。现在尝试:

> cat /dev/pts/4
Run Code Online (Sandbox Code Playgroud)

然后尝试使用 /dev/pts/4 中的 shell。你坚持,直到你退出cat的另一边,但最让你键入点/ 4究竟会通过的(如争取的“Hello World”我结束了hl在点/ 4和ello wordcat控制台)。

我的猜测是,设备正在从 shell 获取输入,并通过系统将其输出,这就是屏幕上显示内容的方式——shell 不是在处理硬件,而是系统。尝试strace bashman strace如果您不知道它是什么,请查看);当 bash 启动时,您会收到一连串的初步呼叫。现在开始敲击键:

read(0, "h", 1)                         = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "h", 1h)                        = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0, "e", 1)                         = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "e", 1e)                        = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0, "y", 1)                         = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "y", 1y)                        = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
Run Code Online (Sandbox Code Playgroud)

对于输入的每个字母,都会从标准输入读取并写入到标准输出。但是外壳的标准输出连接到什么?现在试试strace你的 GUI 终端——如果你不知道它的名字,你必须弄清楚它的名字,例如在 KDE 上它是konsole,而 GNOME 有gnome-terminal,我相信。它的输出strace可能更神秘——我的有很多poll()recvfrom()。我没有看到任何写入,但是如果您现在cat从另一个终端中提取技巧,您会注意到当您键入时,cat 读取的按键在 strace 输出中根本没有任何响应——终端不是t 接收它们。因此,GUI 终端应用程序和 cat 竞争从 shell 输出到的同一设备读取。