C语言 终端原始模式下的异常行为

zdwk9cvp  于 2023-03-07  发布在  其他
关注(0)|答案(2)|浏览(94)

我正在学习一个文本编辑器的教程。到目前为止,它一直在修改原始模式。下面的代码应该关闭规范模式,并输出每个按键。

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>

struct termios orig_termios;
void disableRawMode() { … }
void enableRawMode() { … }

int main() {
  enableRawMode();
  char c;
  while (read(STDIN_FILENO, &c, 1) == 1 && c != 'q') {
    if (iscntrl(c)) {
      printf("%d\n", c);
    } else {
      printf("%d ('%c')\n", c, c);
    }
  }
  return 0;
}

原来忘了在printf()语句后面加上"\n",结果是在程序结束后 * 才得到输出字符,在本例中就是按下q后,而加上"\n"后,终端输出的每个字母都是按下的。
有没有人能好心地解释一下为什么它会这样?

polkgigr

polkgigr1#

原始模式与 * 终端 * 有关,但stdout的缓冲区管理发生在到达终端之前
默认情况下,当文件描述符1STDOUT_FILENO)被链接到终端,则stdout使用-缓冲策略。这意味着当写入\n时,stdout的输出缓冲区将刷新到文件描述符1(或当它满了的时候)。只有在这个时刻角色才能到达终端,终端可以根据其配置以不同的方式做出React。
在您的示例中,字符将一直保留在内存中,直到进程终止(此时刷新stdout)。

lskq00tm

lskq00tm2#

通常,当C程序以连接到终端的标准输出流开始时,该流是行缓冲的。这意味着用printf或标准库方法打印的字符将保留在缓冲区中,直到出现以下情况之一:

  • \n被打印(结束该行,因此“行缓冲”),
  • 缓冲器是满的,
  • 流被手动刷新(与fflush一样),或者
  • 在未缓冲或行缓冲但需要来自“主机环境”(特别是人)的字符的流上请求输入。

终端设置是无关紧要的,因为字符保存在标准C库实现的内部缓冲区中,并且直到发生上述事件之一时才发送到终端。
stdout上执行任何其他操作之前,可以通过调用setvbuf(stdout, NULL, _IONBF, 0)将流设置为unbuffered。

相关问题