【发布时间】:2020-09-03 00:20:09
【问题描述】:
为什么标准流可以在规范模式下从终端接收输入,但是你把它放在原始模式下,突然这个方法不再有效?我非常了解 POSIX 串行编程,通常您使用read。我正在尝试更好地理解标准流。
#include <termios.h>
#include <unistd.h>
#include <iostream>
termios original;
void enableRawMode() {
tcgetattr(STDIN_FILENO, &original);
termios raw = original;
cfmakeraw(&raw);
raw.c_cc[VMIN] = 0;
raw.c_cc[VTIME] = 1;
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
int main() {
enableRawMode();
char c;
// This works as expected.
//int nread;
//while ((nread = read(STDIN_FILENO, &c, 1)) != 1) {
// if (nread == -1 && errno != EAGAIN) {
// break;
// }
//}
// This loops forever, the failbit is always true, gcount is always 0.
while (!(std::cin.get(c))) {
if (std::cin.bad() || std::cin.eof()) {
break;
}
std::cin.clear();
}
tcsetattr(STDIN_FILENO, TCSAFLUSH, &original);
}
【问题讨论】:
-
简短的回答是否定的:这完全不切实际。您必须使用读/写并添加所有特殊逻辑(如 EAGAIN)来处理它。输入/输出流库对 EAGAIN 一无所知,也没有提供相应配置自身的方法。
-
你尝试过不同的 VIM 和 VTIME 值吗?请参阅stackoverflow.com/questions/25996171/… 如果您的程序只是循环,那么它只是轮询系统缓冲区并浪费 CPU 周期。 “这将永远循环,...” -- 无法在 Linux 5.4 上复制此症状;程序退出,不等待任何输入!
-
@sawdust 这个例子只是从更大的整体中抽取的一个相关样本,我知道这很疯狂。请放心,我们会更加关注应用程序中的调度和流程管理。
-
@SamVarshavchik 但是,如果两者绑定和同步,为什么数据会到达标准文件描述符而不是标准流?
-
所以你有借口使用低效的代码。我在 Linux 上获得的结果与您使用的任何 "POSIX" 操作系统有何不同?仅供参考,当
VTIME增加到20时,程序在启动后 2 秒(即 20 分秒)终止。 IOW 该程序似乎确实响应了 termios 设置。你需要更彻底地调试你的程序。
标签: c++ posix iostream termios