终端原始模式下的奇怪行为
Strange behavior in terminal raw mode
我正在学习制作文本编辑器的教程。
到目前为止,它一直在修补原始模式。下面的代码应该关闭规范模式,并输出每个按键。
#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"
之后,终端会按按下的方式输出每个字母。
有谁能解释一下为什么会这样吗?
通常,当 C 程序以连接到终端的标准输出流启动时,该流是行缓冲的。这意味着使用 printf
或标准库方法打印的字符将保留在缓冲区中,直到打印 \n
(结束该行,因此“行缓冲”),缓冲区已满,当流被手动刷新时(与 fflush
一样),或者当在无缓冲或行缓冲的流上请求输入但需要来自“主机环境”(尤其是人类)的字符时。
终端设置无关紧要,因为字符保存在标准 C 库实现的内部缓冲区中,并且直到上述事件之一才会发送到终端。
您可以在对 stdout
执行任何其他操作之前调用 setvbuf(stdout, NULL, _IONBF, 0)
将流设置为无缓冲。
原始模式是终端的关注点,但stdout
的缓冲区管理发生在到达终端之前。
默认情况下,当文件描述符 1
(STDOUT_FILENO
) 是 link 到终端时,stdout
使用 行 -缓冲策略。
这意味着 stdout
的输出缓冲区在写入 \n
时(或已满)刷新到文件描述符 1
。
只有在这一刻,角色才能到达终端,终端可以根据其配置以不同的方式做出反应。
在您的示例中,字符仅保留在内存中,直到进程终止(stdout
此时已刷新)。
我正在学习制作文本编辑器的教程。 到目前为止,它一直在修补原始模式。下面的代码应该关闭规范模式,并输出每个按键。
#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"
之后,终端会按按下的方式输出每个字母。
有谁能解释一下为什么会这样吗?
通常,当 C 程序以连接到终端的标准输出流启动时,该流是行缓冲的。这意味着使用 printf
或标准库方法打印的字符将保留在缓冲区中,直到打印 \n
(结束该行,因此“行缓冲”),缓冲区已满,当流被手动刷新时(与 fflush
一样),或者当在无缓冲或行缓冲的流上请求输入但需要来自“主机环境”(尤其是人类)的字符时。
终端设置无关紧要,因为字符保存在标准 C 库实现的内部缓冲区中,并且直到上述事件之一才会发送到终端。
您可以在对 stdout
执行任何其他操作之前调用 setvbuf(stdout, NULL, _IONBF, 0)
将流设置为无缓冲。
原始模式是终端的关注点,但stdout
的缓冲区管理发生在到达终端之前。
默认情况下,当文件描述符 1
(STDOUT_FILENO
) 是 link 到终端时,stdout
使用 行 -缓冲策略。
这意味着 stdout
的输出缓冲区在写入 \n
时(或已满)刷新到文件描述符 1
。
只有在这一刻,角色才能到达终端,终端可以根据其配置以不同的方式做出反应。
在您的示例中,字符仅保留在内存中,直到进程终止(stdout
此时已刷新)。