终端如何从stdout读取并在屏幕上绘制文本?

use*_*425 8 c unix linux macos bash

我有一个关于终端和流程如何工作的一般性问题.

从任何进程,如果我写入stdout(即文件描述符2),它将在终端窗口上绘制.我的问题是,这是如何实际实现的?stdout是一个实际的'虚拟'文件,终端一直在阅读和在屏幕上绘制内容吗?或者在进程/标准输出流和终端之间是否存在某种IPC?

请注意,当我说终端时,我指的是一些通用的GUI终端/控制台,例如Mac上的终端.

PS如果这个问题不清楚,请告诉我,我很乐意再次尝试解释:)

谢谢!

小智 6

您似乎没有意识到的神奇部分是内核的 tty 层。

\n\n

您打开的每个终端窗口对应于一个伪终端设备\xe2\x80\x94 例如,/dev/ttys001它是 Mac OS X 上此类设备的名称。默认情况下,任何在终端中运行但不运行的进程将其输入/输出从/到其他地方重定向,其标准输入、输出和错误都设置为这些设备之一。例如,如果我在终端中运行的进程lsof上运行,我会看到:cat

\n\n
\n命令 PID 用户 FD 类型设备大小/关闭节点名称\n...\ncat 52919 用户 0u CHR 16,5 0t4562 3313 /dev/ttys005\ncat 52919 用户 1u CHR 16,5 0t4562 3313 /dev/ttys005\ncat 52919用户 2u CHR 16,5 0t4562 3313 /dev/ttys005\n
\n\n

当进程写入伪终端从设备时,输出将路由到持有连接主端的进程(在本例中为您的终端应用程序),该进程可以读取它。类似地,当终端应用程序写入伪终端主设备时,数据可供从相应从设备读取的任何进程使用。

\n\n

伪终端设备还涉及一些其他技巧。最值得注意的是,它们具有固有的行和列大小,其中运行的应用程序可以查询它们,它们可以对通过它们的数据执行某些简单的转换(例如,CR 到 CR/LF、退格到 DEL 等)东西),并且当看到某些字符时它们可以生成信号(例如,Ctrl-C向前台进程生成中断信号)。这里有很多奇怪的历史微妙之处,但重点是内核的 tty 层是大多数这种行为存在的地方。

\n\n

伪终端设备是使用forkpty()libc 函数创建的。其幕后工作原理的细节因平台而异,并且可能会变得非常棘手,因此我不会深入研究细节。

\n


kda*_*zle 5

当您包含 stdio.h 时,stdout 是其中定义的变量。

引用维基百科

stdout - 指向文件的指针,该文件引用标准输出流,通常是显示终端

而且,正如 Russ C 提到的,Unix 中一切都是文件,所以在这方面你是对的。

显然,每个打开的 UNIX 程序默认情况下都将其输出、输入和错误流分别设置为 stdout、stdin 和 stderr 不过,它们是可以改变的。就像在终端中一样,您可以使用“<”重定向文件的标准输入,您可能会在类似的语句中执行此操作

mysql -u root -p dbname < ./data.sql
Run Code Online (Sandbox Code Playgroud)

我想这并不能真正回答您关于实现的真实细节的所有问题,但是知道它是一个文件流可能可以让您很好地了解正在发生的情况。