【发布时间】:2014-11-10 10:43:14
【问题描述】:
一个关于输入终端时回显字符的基本问题。
以一个 Linux 系统为例,cat 命令是从 shell(例如 bash)发出的。现在,据我了解,shell 生成了一个执行 cat 可执行文件的进程,并且在此阶段, cat stdin 和 stdout 已附加到终端。
现在的问题是:shell 是继续从终端接收字符(最终回显它们)还是只接收生成的进程(执行 cat)?
【问题讨论】:
一个关于输入终端时回显字符的基本问题。
以一个 Linux 系统为例,cat 命令是从 shell(例如 bash)发出的。现在,据我了解,shell 生成了一个执行 cat 可执行文件的进程,并且在此阶段, cat stdin 和 stdout 已附加到终端。
现在的问题是:shell 是继续从终端接收字符(最终回显它们)还是只接收生成的进程(执行 cat)?
【问题讨论】:
shell 会将文件描述符 (fd's) 传递给子进程 (cat),但也会转移控制权。因此,只要cat 正在运行,shell 就不会做任何事情,不会接收输入,等等。
从技术上讲,shell forks 和 execs 是子 fork 中的子进程,然后是 waits 以完成子进程。完成后,shell 将等待更多输入(允许您键入下一个命令),然后运行,等等。
【讨论】:
前台进程接收来自终端的输入。无论哪个进程在前台都是唯一接收它的进程(除非它包含将其传递给另一个进程的内部逻辑)。
【讨论】:
shell 不接收字符,只接收前台进程。但这还不是全部。
您键入的内容首先由终端设备驱动程序处理。驱动程序有两种工作模式:规范和非规范。在运行cat 时使用的规范模式下,驱动程序会在您键入字符时回显字符并累积文本行。这允许进行一些基本的编辑,例如使用退格键删除您输入的内容。 cat 在您按下回车键或 Ctrl-D 之前无法看到您输入的内容。
在非规范模式下,终端只是将字符传递给进程而不进行解释或修改:这就是全屏应用程序的工作方式。
【讨论】:
感谢回复,
我做了一个“实验”,强制关闭终端(腻子)本地回声。将 cat 启动到 shell 并发送我可以看到的字符
~ # 猫
你好
你好
~#
对于我输入的每个字符('h' 'e' 'l' 'l' 'o'),我可以在终端屏幕上看到每个字符,然后按回车键,我可以看到整个单词“hello”。
现在,IUUC,屏幕上出现的第一个字符是由于“规范模式”终端设备驱动程序(驱动程序回显它们)。然后就在我点击 Return 时,累积的行 'hello' 被 cat “看到”并从它发送到标准输出(再次是终端屏幕)
有意义吗?
【讨论】:
cat 以行缓冲模式启动(默认情况下),所以一旦你按回车,它就会看到你的“你好”。然后,如果您使用 ^D 退出 cat,shell 将接收您接下来键入的任何内容。
read 返回的内容及其调用方式时,我看到 Bash 一个一个请求字符,但我看到 cat 处于行缓冲模式;所以read 被要求获得更长的缓冲区。在我的情况下 (MacOSX) cat 要求 read 从 fd 0 (stdin) 获取 131072 个字符; read 然后返回看到 6 个字符(你好加上换行符)。如果您想窥探此类 libc 调用:我已在 kubat.nl/pages/blogaria/310 上发表了一篇简短的博文。
cat 只会在您按 Enter 后看到您的 hello 而不会在之前看到;所以cat 本身永远无法回显单独的字符。