Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么'ioctl(fd,EVIOCGRAB,1)`有时会导致密钥垃圾邮件?_C_Linux_Keyboard_Ubuntu 14.04 - Fatal编程技术网

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

为什么'ioctl(fd,EVIOCGRAB,1)`有时会导致密钥垃圾邮件?,c,linux,keyboard,ubuntu-14.04,C,Linux,Keyboard,Ubuntu 14.04,我正在尝试编写我自己的“键盘驱动程序”(实际上没有编写内核模块), 通过抓住键盘,我认为这是userland中最底层的抽象:/dev/input/event* 以下代码执行抓取操作,前提是您更改ioctl(fd、EVIOCGRAB、UNGRAB)的第一次出现次数 到ioctl(fd,EVIOCGRAB,GRAB) //gcc main.c-o main #包括 #包括 #包括 #包括 #包括 #包括 #定义退出键 #定义UNGRAB 0 #定义抓取1 const char*kbd_device=

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

以下代码执行抓取操作,前提是您更改
ioctl(fd、EVIOCGRAB、UNGRAB)的第一次出现次数
ioctl(fd,EVIOCGRAB,GRAB)

//gcc main.c-o main
#包括
#包括
#包括
#包括
#包括
#包括
#定义退出键
#定义UNGRAB 0
#定义抓取1
const char*kbd_device=“/dev/input/event4”;
// ------------------------------------------------------------------------------------------------
内部主(空){
int fd=打开(仅限kbd_设备);
如果(fd==-1){
printf(“无法打开%s.%s.\n”,kbd_设备,strerror(errno));
返回-1;
}
if(ioctl(fd、EVIOCGRAB、UNGRAB))
printf(“无法获取%s.%s.\n”,kbd_设备,strerror(errno));
其他的
printf(“抓取%s!\n”,kbd_设备);
而(1){
结构输入事件;
读取(fd、事件和sizeof(事件));
如果键入时(event.type==EV_KEY&&event.value>=0&&event.value)

gcc main.c -o main && sudo ./main ↵
sudo ./main ↵
GCC需要一些时间,因此↵ 当
/main
运行时,按键已释放

你打字的时候

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

只要你按下按钮,终端就会向外壳发送一条新行↵, 并开始执行
/main
↵ 释放的事件会被你的程序看到,但不会被你的终端看到,因为你的程序已经抓取了输入设备↵ 这个问题已经得到了回答,但它仍然缺乏一个优雅的解决方案

我之前实现的一个驱动程序也有同样的问题,它还需要捕获键盘

我无法找到一种方法来强制内核在捕获设备之前识别设备中的密钥释放,因此解决方案是在检测到所有密钥都已实际释放之前不捕获设备。这可以通过在打开设备后和捕获设备之前使用eviockey ioctl监视设备来实现

OBS:请注意,
while
循环中的显然是虚拟的
read
函数是必要的,以避免繁忙的等待,这样循环将在来自输入设备的每个事件之后迭代。还请注意,必须将文件描述符配置为阻止I/O(默认设置)

void waitReleaseAll(int-fd){
结构输入事件evt;
无符号字符密钥b[密钥最大/8+1];
int i,无;
而(1){
memset(key_b,0,sizeof(key_b));
ioctl(fd,EVIOCGKEY(sizeof(key_b)),key_b);
对于(无=1,i=0;i
要解决问题,您应该在代码中使用
SIGINT
来识别用户的
Ctrl-C
击键

在代码中执行
信号

2个有效的解决方案是:1)快速执行一个不抓取的
ioctl
,然后执行一个抓取的(即
ioctl(input.fd,EVIOCGRAB,UNGRAB);ioctl(input.fd,EVIOCGRAB,grab);
),2)在启动时增加100毫秒的睡眠时间。不起作用的是:向
/dev/uinput
(这对发送其他击键有效)。有更优雅的解决方案吗?
uinput
可能不起作用,因为一个键盘上的按键释放!=另一个键盘上的按键释放:(假设您在X中运行:如果您的X具有
logind
集成,您可以将设备分配到另一个座位,该座位应将其从X中移除。或者您可以在抓取设备之前使用xinput禁用从该设备到X的输入。不过,无论采用哪种方式,您都需要某种恢复方式。
static volatile sig_atomic_t stop = 0;
    
static void interrupt_handler(int sig)
{
    stop = 1;
} // Outside of the main function.

int main(int argc, char *argv[])
{
    signal(SIGINT, interrupt_handler);
    while (!stop) {
    //your code    
    }
    exit(0);
}