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

标签 c linux keyboard ubuntu-14.04

我正在尝试编写自己的“键盘驱动程序”(实际上没有编写内核模块), 通过在我认为是用户空间中最低抽象级别的地方捕获键盘:/dev/input/event*

如果您更改 ioctl(fd, EVIOCGRAB, UNGRAB) 的第一次出现,则以下代码执行抓取 到 ioctl(fd, EVIOCGRAB, GRAB)

// gcc main.c -o main

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <linux/input.h>
#include <fcntl.h>
#include <errno.h>

#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 上运行,但不能在 X 上运行(例如 TTY)。

我知道 X11 的键盘库/扩展是 XKB。我认为 TTY 的键盘库是 linux/divers/tty/vt/keyboard.c ( source ), 它使用的初始键盘映射位于 linux/drivers/tty/vt/defkeymap.map ( source ) 中,可以使用 loadkeys 对其进行修改(来源 here )。如果我错了,请纠正我。

最佳答案

当你输入时

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

GCC 需要一些时间,所以 key 在 ./main 运行时已经释放。

当你输入时

sudo ./main ↵

当您按下 时,终端会立即向 shell 发送一个换行符,并开始执行 ./main。然后 released 事件会被你的程序看到,但不会被你的终端看到,因为你的程序已经捕获了输入设备。因此,对于终端来说,它看起来像 被卡住了,所以它继续产生换行符。

关于c - 为什么 `ioctl(fd, EVIOCGRAB, 1)` 有时会导致 key 垃圾邮件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41995349/

相关文章:

linux - 在 Linux 上安装 tar.gz

linux - 如何安装 wkhtml2pdf?

ios - 如何在用户点击键盘上返回时单击 UIButton

iphone - UITextField - 检测内置 iPhone 键盘上的输入?

c函数重复执行而不被调用,导致段错误

c - 使用其他 Const Struct 实例初始化 Const Struct

c - 等待子进程不超过 X 秒

linux - inode 数据结构中的数据指针

javascript - 如何记录短时间内的按键/键盘事件?

c - 有没有一种简单的方法可以从数组中删除项目?