【问题标题】:Who echos the characters in terminal?谁在终端中回显字符?
【发布时间】:2012-12-28 20:31:06
【问题描述】:

让我们看看下面的代码:

int main(void)
{
             char c;

             while ((c = getchar()) != EOF)
                     putchar(c);

             return (0);
 }

此程序仅在新行作为字符传递后才回显字符。 我尝试使用 read 系统调用直接读取并将 len 作为 1 传递,它仍然仅在传递新行时读取。我这里有两个问题:谁实现了这个优化,是内核还是终端/shell?

其次,谁在第一时间回显字符,也就是在第一次印刷本身。终端/shell 在这个程序的整个执行过程中是否起任何作用?

【问题讨论】:

  • 我知道 shell 有点负责任:当你调用它时,无论有没有重定向,程序的行为都会有所不同:./a.out vs ./a.out < input.txt > output.txt vs ...

标签: c io terminal


【解决方案1】:

外壳无关紧要。您键入的 tty(假设它不是原始模式,并且启用了回显)在您键入字符时显示字符,但在您键入 enter 之前不会将它们传递给进程。它处理所有退格和编辑等,而您的进程永远不会看到这些。当您按 Enter 键时,tty 会将输入的行传递给进程。

【讨论】:

    【解决方案2】:

    当一个任务正在执行时(例如你的程序),它处于“RUNNING”状态。

    当程序请求键盘输入时,内核暂停你的程序并将键盘输入连接到程序内存中的缓冲区(由 IA32 架构中的 LDT 和 GDT 寄存器维护)

    通过IVT(Interrupt Vector Table)中的特定中断函数读取键盘数据(该表在IA32 Arch中使用IDTs维护)

    当遇到新行时(通过按键盘上的 ENTER 键),输入缓冲区关闭,任务从“暂停”状态变为“就绪”状态。

    多任务内核几乎没有“时间”来等待用户输入并将其回显到输出。相反,它将键盘连接到缓冲区,然后去执行其他重要任务(例如任务调度)。当程序处于“运行”状态,并且键盘缓冲区被填满时,它会从缓冲区中读取输入,并将其写入输出缓冲区。

    然而,Shell 只是一个由内核调度的程序。它不能直接访问键盘,但可以访问内核分配的特定键盘缓冲区。

    【讨论】:

    • 虽然必须为程序 [或操作系统] 设置 LDTR 和 GDTR 才能运行,但它与键盘的缓冲方式关系不大,因为这就像任何其他的内存中的数据[除非你运行的是 OS/2 1.x - 但我猜问这类问题的人并不多!]
    • @MatsPetersson 我在编写自己的玩具操作系统时学会了这项技术。但我认为整个缓冲取决于 stdlib 实现者。
    • 另外,“键盘输入”并不总是来自键盘。例如,如果我使用 SSH 连接到另一台计算机,则输入通过网线传输到另一端,读取“键盘”的过程实际上是从伪 tty 读取的,该伪 tty 由sshd 提供守护进程。同样,如果您有一个xterm shell,而不是 Linux 中的 VGA 或 FB 屏幕,则键盘输入通过伪终端进行
    • @MatsPetersson 我希望伪终端能够模拟击键。
    • stdlib 不是(通常)实现的地方,而是在键盘驱动程序中。如果您使用零作为文件描述符调用 read,它仍会缓冲输入。并且读取没有在 C 库中实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    • 2014-04-29
    • 2011-05-16
    • 2010-12-20
    • 1970-01-01
    • 2014-09-20
    相关资源
    最近更新 更多