小智 6
您似乎没有意识到的神奇部分是内核的 tty 层。
\n\n您打开的每个终端窗口对应于一个伪终端设备\xe2\x80\x94 例如,/dev/ttys001它是 Mac OS X 上此类设备的名称。默认情况下,任何在终端中运行但不运行的进程将其输入/输出从/到其他地方重定向,其标准输入、输出和错误都设置为这些设备之一。例如,如果我在终端中运行的进程lsof上运行,我会看到:cat
\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 函数创建的。其幕后工作原理的细节因平台而异,并且可能会变得非常棘手,因此我不会深入研究细节。
当您包含 stdio.h 时,stdout 是其中定义的变量。
引用维基百科
stdout - 指向文件的指针,该文件引用标准输出流,通常是显示终端
而且,正如 Russ C 提到的,Unix 中一切都是文件,所以在这方面你是对的。
显然,每个打开的 UNIX 程序默认情况下都将其输出、输入和错误流分别设置为 stdout、stdin 和 stderr 。不过,它们是可以改变的。就像在终端中一样,您可以使用“<”重定向文件的标准输入,您可能会在类似的语句中执行此操作
mysql -u root -p dbname < ./data.sql
Run Code Online (Sandbox Code Playgroud)
我想这并不能真正回答您关于实现的真实细节的所有问题,但是知道它是一个文件流可能可以让您很好地了解正在发生的情况。