为此所需的代码相当复杂;我最终想出了如何在 C 中使用原始 ioctl、读取和写入来检查 F1。如果您熟悉汇编和 Linux 系统调用,那么转换为 nasm 应该很简单。
这并不完全是您想要的,因为它只检查 F1,而不检查其余部分。 F1的序列是0x1b、0x4f、0x50。您可以使用od -t x1 并按 键找到其他序列。例如,F2 为 0x1b、0x4f、0x51。
基本思想是我们获取当前终端属性,将它们更新为原始(cfmakeraw),然后将它们设置回来。为此使用 ioctl 系统调用。
在原始模式下的终端上,read() 将获取用户输入的任何字符,这与内核使用退格键和 control-u 进行行编辑的“熟”模式不同,直到用户提交该行通过按 enter 或 control-d (EOF)。
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
struct ktermios {
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[19];
};
int getch() {
unsigned char c;
read(0, &c, sizeof(c));
return c;
}
int main(int argc, char *argv[]) {
struct ktermios orig, new;
ioctl(0, TCGETS, &orig);
ioctl(0, TCGETS, &new); // or more simply new = orig;
// from cfmakeraw documentation
new.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
new.c_oflag &= ~OPOST;
new.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
new.c_cflag &= ~(CSIZE | PARENB);
new.c_cflag |= CS8;
ioctl(0, TCSETS, &new);
while (1) {
if (getch() == 0x1b && getch() == 0x4f && getch() == 0x50) {
break;
}
}
write(1, "Got F1!\n", 8);
ioctl(0, TCSETS, &orig); // restore original settings before exiting!
return 0;
}
我根据this answer 做了这个,这很有帮助。