如何在Unix中从键盘设备中捕获用户输入?

10
我想从键盘设备中捕获所有用户输入,逐字节地读取。我已经写了下面这段代码,但它没有起作用:
if ((fd = open("/dev/char", O_RDONLY) != 1) {
    tty = open("/dev/tty", O_RDONLY);
    tcsetattr(0, TCSANOW, &orig_info);
    read (fd, &buf, sizeof(char));
}
close(fd);

我本以为终端会等待输入,但它没有。

不,只需从fd 0读取。 - Ulrich Dangel
2个回答

15

键盘设备本身是在/dev/input中的一个条目。您可以通过它们的连接类型(例如PS/2、USB等)在/dev/input/by-path中查找键盘和其他输入设备。显然,您需要以root用户运行才能直接访问硬件,并且您需要将来自键盘的原始字节转换为诸如按键和释放键等内容。这可能不是您想要的。

如果您正在运行GUI应用程序,则低级方法是调用XNextEvent等函数。解码输入事件并不完全简单,因为应用程序应用修饰符。GUI框架(Motif、Gtk、Qt等)将有助于您。

如果您正在运行终端应用程序,请从标准输入或/dev/tty中读取(即使标准输入已被重定向,/dev/tty始终是程序正在运行的终端)。您需要将终端设置为 raw 模式。您将获得解码的字符键和功能键,主要作为转义序列。在这里,库也是有用的;事实上,标准是ncurses


2

你想要做什么?

如果你正在寻找终端中的非缓冲输入,那么 tcsetattr() 就是你要找的 - 你需要将终端设置为非规范模式,即将终端标志位设置为不包含 ICANON - 可以参考 this code snippet。请查看 man termios(或函数名,它通常在 Linux 上链接到同一个 man 页面)。

如果你想要独占访问键盘,那就更加复杂了。


@BunnyBunny,事实上,在大多数情况下,你不需要直接从键盘读取输入 - Gilles的回答已经很好地总结了这一点(像他一贯的风格一样 :))。这就是为什么最好描述你试图解决的问题 - 这可能会发现你并没有朝着最佳方向前进。 - peterph
@peterph 这个问题非常简单。打开键盘设备,逐字节读取。要控制键盘,我们必须显式地打开 /dev/tty。 - Bunny Bunny
1
@BunnyBunny /dev/tty 不是键盘设备,它是处理输入的(在远程 shell 的情况下甚至不需要是本地键盘)。这就是为什么我写道说明您的问题可能会有所帮助 - “我需要打开键盘设备”不是您要解决的问题 - 而是类似于“我需要一次从用户读取一个字符的密码输入,并且不能在屏幕上显示”或“我需要捕获所有键盘输入”。提供更多上下文将获得更好的答案。 - peterph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接