这里你似乎没有意识到的神奇部分是内核的tty层。 您打开的每个终端窗口都对应一个pseudoterminal device-例如,/dev/ttys001是Mac OS X上一个这样的设备的名称。默认情况下,在终端中运行的任何进程,如果没有将其输入/输出重定向到其他位置,则其标准输入,输出和错误都设置为这些设备之一。例如,如果我在终端中运行的cat进程上运行lsof,我看到:
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
3条答案
按热度按时间rslzwgfq1#
这里你似乎没有意识到的神奇部分是内核的tty层。
您打开的每个终端窗口都对应一个pseudoterminal device-例如,
/dev/ttys001
是Mac OS X上一个这样的设备的名称。默认情况下,在终端中运行的任何进程,如果没有将其输入/输出重定向到其他位置,则其标准输入,输出和错误都设置为这些设备之一。例如,如果我在终端中运行的cat
进程上运行lsof
,我看到:字符串
当一个进程写入一个伪终端从设备时,输出被路由到持有连接的主端的进程(在本例中,是您的终端应用程序),该进程可以读取它。类似地,当一个终端应用程序写入一个伪终端主设备时,数据对任何从相应的从设备阅读的进程都可用。
伪终端设备还有一些其他的技巧,最值得注意的是,它们具有固有的行和列的大小,在其中运行的应用程序可以查询这些大小,它们可以对通过它们的数据执行某些简单的转换(例如,CR到CR/LF,退格键到DEL,以及其他类似的事情),并且当看到某些字符时,它们可以生成信号(例如,Ctrl-C向前台进程生成一个中断信号)。这里有很多奇怪的历史微妙之处,但关键是内核的tty层是大多数这种行为存在的地方。
伪终端设备是使用
forkpty()
libc函数创建的,其幕后工作的细节因平台而异,可能会变得非常复杂,所以我不会深入研究细节。yuvru6vn2#
当你包含stdio. h时,stdout是一个定义在那里的变量。
引用Wikipedia
stdout -指向FILE的指针,该FILE引用标准输出流,通常是显示终端
而且,正如Russ C提到的,在Unix中一切都是文件,所以你在这方面是对的。
还有apparently,每个打开的unix程序都有其输出、输入和错误流,默认情况下,分别设置为stdout、stdin和stderr。不过,它们是可以更改的。比如在terminal中,您可以通过使用“<$”来redirect文件的标准输入,您可能会在以下语句中这样做:
字符串
我想这并不能真正回答您关于实现的所有细节的问题,但是知道它是一个文件流可能会让您给予一个很好的概念。
5sxhfpxr3#
这是一个大画面。
1.终端是一个设备,它是一个硬件,你可以通过向它的硬件接口写入数据来让东西出现在它上面。
1.操作系统把这个(和任何硬件设备)的处理委托给设备驱动程序。设备驱动程序本质上提供了一个到设备的软件接口。然后你可以通过调用这个设备驱动程序软件接口来让东西出现在终端上。
1.在 *nix系统中,设备驱动程序将它们控制的硬件设备作为文件暴露在文件系统中。您可以打开这些文件,并调用设备驱动程序提供的软件接口(通过open,ioctl,close等)。
1.默认情况下,当创建一个进程时,描述符1和2会在终端设备上打开。因此,当您写入这些描述符时,底层驱动程序会接收数据,并与硬件设备对话以在屏幕上呈现字符。
1.当您将一个进程的输出通过管道传输到另一个进程或将输出重定向到一个文件时,描述符将重新打开到其他设备(如管道或文件),并且您写入其中的数据将最终到达相应的设备驱动程序,并最终到达硬件设备。