为什么`ioctl(fd,EVIOCGRAB,1)`有时会导致密钥垃圾邮件?

我正在尝试编写自己的“键盘驱动程序”(没有实际编写内核模块),通过抓取键盘,我认为是userland中最低级别的抽象: /dev/input/event*

如果您将ioctl(fd, EVIOCGRAB, UNGRAB)的第一个更改更改为ioctl(fd, EVIOCGRAB, GRAB)以下代码执行此操作。

 // gcc main.c -o main #include  #include  #include  #include  #include  #include  #define EXIT_KEY KEY_ESC #define UNGRAB 0 #define GRAB 1 const char* kbd_device = "/dev/input/event4"; // ------------------------------------------------------------------------------------------------ int main(void){ int fd = open(kbd_device, O_RDONLY); if(fd == -1){ printf("Cannot open %s. %s.\n", kbd_device, strerror(errno)); return -1; } if(ioctl(fd, EVIOCGRAB, UNGRAB)) printf("Couldn't grab %s. %s.\n", kbd_device, strerror(errno)); else printf("Grabbed %s!\n", kbd_device); while(1){ struct input_event event; read(fd, &event, sizeof(event)); if (event.type == EV_KEY && event.value >= 0 && event.value <= 2){ printf("%d %3d\n", event.value, event.code); if(event.code == EXIT_KEY){ ioctl(fd, EVIOCGRAB, UNGRAB); close(fd); return 0; } } } } 

问题

  • 如果我运行gcc main.c -o main && sudo ./main ,一切都按预期工作。
  • 如果先编译然后我运行sudo ./main ,则终端会不停地向下滚动,就像按住RETURN键一样。

为什么会这样?

笔记

  • 我正在运行Ubuntu 14.04
  • 在我的平台上, /dev/input/event4恰好是键盘

动机

我正在尝试编写一个键盘“驱动程序”,它既可以在X上运行,也可以在X上运行(例如,一个TTY)。

我理解X11的键盘库/扩展名是XKB。 我认为TTY的键盘库是linux/divers/tty/vt/keyboard.c ( 源码 ),它使用的初始键盘映射是linux/drivers/tty/vt/defkeymap.map ( 源码 ),可以修改通过使用loadkeys (源在这里 )。 如果我错了,请纠正我。

当你输入

 gcc main.c -o main && sudo ./main ↵ 

GCC需要一些时间,因此键已经在./main运行时./main

当你输入

 sudo ./main ↵ 

一旦你按下 ,终端就会向shell发送换行符,然后开始执行./main 。 然后,您的程序会看到发布的事件,但不是您的终端,因为您的程序已经抓住了输入设备。 因此,到终端看起来被卡住了,所以它继续产生换行符。