为什么`ioctl(fd,EVIOCGRAB,1)`有时会导致关键垃圾邮件? [英] Why does `ioctl(fd, EVIOCGRAB, 1)` cause key spam sometimes?
问题描述
我正在尝试编写自己的键盘驱动程序"(实际上并未编写内核模块),
通过抓住我认为是用户界面中最低的抽象级别的键盘:/dev/input/event*
.
I'm trying to write my own "keyboard driver" (without actually writing a kernel module),
by grabbing the keyboard at what I assume is the lowest level of abstraction in userland: /dev/input/event*
.
如果您更改ioctl(fd, EVIOCGRAB, UNGRAB)
的第一次出现,以下代码将进行抓取
到ioctl(fd, EVIOCGRAB, GRAB)
.
The following code does the grabbing, provided you change the first ocurrence of ioctl(fd, EVIOCGRAB, UNGRAB)
to 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键一样. - If I run
gcc main.c -o main && sudo ./main
, everything works as expected. - If first compile and then I run
sudo ./main
, however, the terminal scrolls down nonstop, as if the RETURN key was held down. - 我正在运行Ubuntu 14.04
- 在我的平台上,
/dev/input/event4
恰好是键盘 - I'm running Ubuntu 14.04
- On my platform,
/dev/input/event4
happens to be the keyboard
Problem
为什么会发生?
我正在尝试编写一个既可以在X上又不能在X上使用的键盘驱动程序"(例如TTY).
I'm trying to write a keyboard "driver" that works both on X and not on X (eg. a TTY).
我了解X11的键盘库/扩展名是XKB.我认为TTY的键盘库是linux/divers/tty/vt/keyboard.c
(源),
它使用的初始键盘映射在linux/drivers/tty/vt/defkeymap.map
中( source ),并且可以使用loadkeys
(源
I understand X11's keyboard library/extension is XKB. I think the TTY's keyboard library is linux/divers/tty/vt/keyboard.c
(source),
the initial keyboard map it uses is in linux/drivers/tty/vt/defkeymap.map
(source), and it can be modified by using loadkeys
(source here). Do correct me if I'm wrong.
推荐答案
键入时
gcc main.c -o main && sudo ./main ↵
GCC需要一些时间,因此↵密钥在./main
运行时已被释放.
GCC takes some time, so the ↵ key has been released by the time ./main
runs.
键入时
sudo ./main ↵
一旦按下↵,终端就会向shell发送换行符,并开始执行./main
.然后,您的程序而不是终端会看到↵释放事件,因为您的程序已抓住了输入设备.因此,对于终端而言,↵似乎被卡住了,因此它继续产生换行符.
the terminal sends the shell a newline as soon as you push down ↵, and starts executing ./main
. Then the ↵ released event is seen by your program, but not by your terminal, because your program has grabbed the input device. Thus, to the terminal it looks like ↵ is stuck down, so it continues to produce newlines.
这篇关于为什么`ioctl(fd,EVIOCGRAB,1)`有时会导致关键垃圾邮件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!