我有一个关于终端和进程如何工作的一般性问题。
在任何进程中,如果我写入标准输出(即文件描述符 2),它就会被绘制在终端窗口上。我的问题是,这实际上是如何实现的?stdout 是否是终端不断读取并在屏幕上绘制内容的实际“虚拟”文件?或者进程/标准输出流和终端之间是否存在某种 IPC?
请注意,当我说终端时,我指的是一些通用的 GUI 终端/控制台,例如 Mac 上的终端。
PS如果这个问题不清楚,请告诉我,我会很乐意再次解释:)
谢谢!
The magic part here that you don't seem to be aware of is the kernel's tty layer.
Each terminal window you open corresponds to a pseudoterminal device — for instance, /dev/ttys001
is a name for one such device on Mac OS X. By default, any process that's running in a terminal and which doesn't have its input/output redirected from/to somewhere else, its standard input, output, and error are all set to one of these devices. For instance, if I run lsof
on a cat
process running in a terminal, I see:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME ... cat 52919 user 0u CHR 16,5 0t4562 3313 /dev/ttys005 cat 52919 user 1u CHR 16,5 0t4562 3313 /dev/ttys005 cat 52919 user 2u CHR 16,5 0t4562 3313 /dev/ttys005
When a process writes to a pseudoterminal slave device, the output is routed to the process holding the master end of the connection (in this case, your terminal application), which can read it. Similarly, when a terminal application writes to a pseudoterminal master device, the data becomes available to any process that's reading from the corresponding slave device.
There are a few other tricks involved with pseudoterminal devices. Most notably, they have an inherent size in rows and columns, which an application running in them can query, they can perform certain simple translations on data passing through them (for instance, CR to CR/LF, backspace to DEL, and other such things), and they can generate signals when certain characters are seen (e.g, Ctrl-C generates an interrupt signal to the foreground process). There's a lot of weird historical subtleties here, but the point is that the kernel's tty layer is where most of this behavior exists.
Pseudoterminal devices are created using the forkpty()
libc function. The details of how this works behind the scenes vary from platform to platform, and can get pretty hairy, so I won't dig into the details.
当您包含 stdio.h 时,stdout 是在那里定义的变量。
引用维基百科
stdout - 指向标准输出流的 FILE 的指针,通常是显示终端
而且,正如 Russ C 所提到的,在 Unix 中一切都是文件,所以在这方面你是对的。
显然,每个打开的 unix 程序都有其输出、输入和错误流,默认情况下分别设置为 stdout、stdin 和 stderr。不过,它们可以更改。就像在终端中使用'<'重定向文件的标准输入一样,你可能会在如下语句中执行此操作
mysql -u root -p dbname < ./data.sql
我想这并不能真正回答你关于实现的真正细节的所有问题,但知道它是一个文件流可能会让你对正在发生的事情有一个很好的了解。
这是大图。