【发布时间】:2021-03-18 08:53:11
【问题描述】:
阅读过各种资源,包括http://www.linusakesson.net/programming/tty/ 我仍然对伪终端的结构和使用感到困惑和好奇 在 linux 终端(bash 不是 tty)中,我们有三个流:
- 标准输入
- 标准输出
- 标准错误
每个都有一个文件描述符。 这些文件描述符映射到流 FILE*。 例如,我们可以使用 fileno() 和 fdopen() 在它们之间进行切换。
我可以用 pty 做什么?
我通常认为 stdout、stdin 和 stderr 与一个进程相关联。 我认为说有一个与 pty 关联的 stdout、stdin 和 stderr 是不正确的。 所以给定一个 pty(对于像 bash 这样的进程而不是它的 pid),你如何获得它们并将它们连接到 bash 意义上的终端?
单个文件描述符(用于 pty)如何映射到三个流? (显然不是) 它可以以某种方式映射到进程吗?
使用 openpty() 时,我认为要连接主终端和从终端上的进程,您需要为 stdin、stdout 和 stderr 设置单独的管道,并有一个选择循环连接它们并传输它们之间的数据。
但是您是否可以假设 stdin 和 stdout 是连接的(通过 tty)并只是设置一个 stderr 管道以避免 stdout 和 stderr 被合并?
如果我们有一个主从进程,那么“额外”的 tty 实际上为我们做了什么?
以下是我认为我知道并且相关的一些事情:
openpty() 函数返回一对文件描述符,表示伪终端的主从端。
每个文件描述符都指向字符设备 - 见https://man7.org/linux/man-pages/man7/pty.7.html
现在 Unix 中的设备只是特殊文件,因此文件描述符是有意义的。
bash 终端具有三个流,但 tty 只是一个通道(stdout 和 stderr 之间没有区别)。 虚拟终端 (tty) 也有一些“魔法”(例如,线路规程)。
如果我要问 FD 将 pty 映射到哪个文件,那将是设备文件 /dev/ptyX 或其他什么。
在主/从通道的任一端都有一个“终端”,由 openpty() 创建。
它实际传输什么数据?
我通常将文件描述符视为对表示文件的内核结构表的索引。 很明显,其中一些文件是流(FILE* 的内核版本),其中一些是流 很特别。
与终端(tty)相关的主要用户空间结构是使用 tcgetattr 从 FD 获得的 termios。 这使您可以为终端设置参数,但它不会识别任何流或进程 或线路纪律。
对于您认为是文件的 FILE* 或 fd,有一组非常清晰且易于使用的 API 定义了您可以做什么。
我隐约知道我可以用字符设备做什么(例如https://unix.stackexchange.com/questions/37829/how-do-character-device-or-character-special-files-work)。
但是你可以用 pty 做什么呢?
给定一个流,我们可以使用 isatty() 确定它是否具有关联的 tty,并使用 ttyname() 识别该 tty。 所以在内部某处有一些东西知道 tty 和流相关联。 isatty(STDERR_FILENO) 也是如此,所以它不仅仅是标准输入和标准输出。
最初引起我兴趣的是一个应该是守护进程但创建 ncurses UI 的程序。我一直在考虑如何使流程按需打开其 ncurses UI(在 pty 中)。屏幕程序允许您执行此操作,但它在幕后做了什么。
描述此用例的问题是 - attach a terminal to a process running as a daemon (to run an ncurses UI)
从面向对象的角度来看这个问题的另一种方式。
有哪些函数将“pty”作为参数。它们是用来做什么的? 如果我有一个 pty 对象。会有哪些方法?
如果您仅列出这些功能,手册页中会缺少一些关键信息。什么是前置条件、后置条件和不变量。
【问题讨论】:
-
我有偏见,但我认为这很好地证明了 pty 何时有用。特别注意 pty 在测试套件中的使用方式:github.com/wrp/smtx
-
“单个文件描述符(用于 pty)如何映射到三个流?” fdopen“(显然没有)”为什么不呢?
-
@rici - 如果是,那怎么办?
-
另请参阅我的新问题 - stackoverflow.com/questions/65282503/…