input专题--独占事件

news2024/11/18 13:39:05

最近在群里聊天,遇到一个哥们描述的一个问题:

大家好,请教一个关于文件的问题。有几个进程打开了/dev/input 设备,都可以收到数据,又来了一个进程x,打开了这个设备,不知道采用了什么方式,其他的进程都收不到数据了,只有x可以收到,请问是怎么实现数据独占的呢?

对于这个问题,其实在之前的 input子系统 -- 05 数据上报

这篇文章中有过描述

input_sync() -> input_event() -> input_handle_event() -> input_pass_values()

static void input_pass_values(struct input_dev *dev,
			      struct input_value *vals, unsigned int count)
{
	struct input_handle *handle;
	struct input_value *v;
 
	if (!count)
		return;
 
	rcu_read_lock();
 
	handle = rcu_dereference(dev->grab);
	if (handle) {
        /* 处理独占事件 */
		count = input_to_handler(handle, vals, count);
	} else {
        /* 非独占,所有应用程序都会收到 */
		list_for_each_entry_rcu(handle, &dev->h_list, d_node)
			if (handle->open) {
				count = input_to_handler(handle, vals, count);
				if (!count)
					break;
			}
	}
 
        ...
}

这里的grab的意思是设备被抓或者设备被独占的意思,通过EVIOCGRAB ioctl设置,设置后当前设备变成唯一的来自设备的所有输入事件的接收者。

对于独占功能是如何配置的,我也是第一次使用,现在看一下内核驱动独占功能代码的实现

文件 drivers/input/evdev.c

static long evdev_do_ioctl(struct file *file, unsigned int cmd,
               void __user *p, int compat_mode)
{
    struct evdev_client *client = file->private_data;
    struct evdev *evdev = client->evdev;
    struct input_dev *dev = evdev->handle.dev;
    struct input_absinfo abs;
    struct input_mask mask;
    struct ff_effect effect;
    int __user *ip = (int __user *)p;
    unsigned int i, t, u, v;
    unsigned int size;
    int error;

    /* First we check for fixed-length commands */
    switch (cmd) {
    ....
    case EVIOCGRAB:
        if (p)
            /* 设置独占 */
            return evdev_grab(evdev, client);
        else
            /* 取消独占 */
            return evdev_ungrab(evdev, client);
    ....
}

这部分代码可以看出,是否设置独占是根据p值设置的,而这个p值是应用程序传递下来的

那么应用程序可以这样写

int fd;
fd = open("/dev/input/event0", O_RDWR);
/* enable grab */
ioctl(fd, EVIOCGRAB, (void *)1);
/* disable grab */
ioctl(fd, EVIOCGRAB, (void *)0);

编写应用代码测试

#include <stdio.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define EVENT_NUM 4
#define DEV_EVENTX "/dev/input/event"

int main(int argc, char *argv[])
{
    int fd[EVENT_NUM];
    int maxnum = 0;
    int select_r;
    fd_set fds, fds_init;
    struct input_event ev; 
    int i = 0;
    char event_path[32];
    int enable_grab = 0;

    if (argc > 1) {
        if (*argv[1] == '1')
            enable_grab = 1;
    }

    FD_ZERO(&fds_init);

    for (i = 0; i < EVENT_NUM; i++) {
        memset(event_path, 0, sizeof(event_path));
        sprintf(event_path, "%s%d", DEV_EVENTX, i); 
        fd[i] = open(event_path, O_RDWR);
        if (fd[i] < 0) {
            printf("Open %s failed!\n", event_path);
        } else {
            if (fd[i] > maxnum) {
                maxnum = fd[i];
            }
            FD_SET(fd[i], &fds_init);
            if (enable_grab)
                ret = ioctl(fd[i], EVIOCGRAB, (void*)1);
                if (ret < 0)
                    printf("error: %d\n", errno);
        }
    }

    while(1) {
        fds = fds_init;
        select_r = select(maxnum+1, &fds, NULL, NULL, NULL);
        if (select_r < 0) {
            fprintf(stderr, "select error!\n");
            break;
        }

        for(i = 0; i < EVENT_NUM; i++) {
            if (FD_ISSET(fd[i], &fds)) {
                read(fd[i], &ev, sizeof(struct input_event));
                if (ev.type != EV_SYN)
                    printf("type: %d, code: %d, value: %d\n", ev.type, ev.code, ev.value);
            }
        }
    }

 实际运行测试结果如下:

可以看到当使能独占的时候,其他的应用就会收不到input的上报信息了

这里拓展一下如果,再有一个应用程序使能独占的话,会发生什么?

内核代码中可以看到

static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
{
    int error;

    if (evdev->grab)
        return -EBUSY;

    error = input_grab_device(&evdev->handle);
    if (error)
        return error;

    rcu_assign_pointer(evdev->grab, client);

    return 0;
}

应该是返回-EBUSY

 和之前分析的一样!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/353126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++框架学习一:朴实无华的高性能RPC框架推荐

一个高性能的RPC框架&#xff1a; 介绍&#xff1a; 框架特性 操作系统&#xff1a;Linux编程语言&#xff1a;C14完全独立&#xff1a;不依赖任何第三方库高性能&#xff1a;微秒级响应高并发&#xff1a;单机百万连接IO多路复用&#xff1a;epoll连接池线程池用法简单 服…

快速入门nginx

目录 1.nginx前言 2.什么是nginx 3.Nginx作用&#xff1f; 1.正向代理 2.反向代理 3.轮询 4.加权轮询 4.Nginx的安装 1.windows下安装 2.linux下安装 5.Nginx常用命令 1.nginx前言 我们公司项目刚刚上线的时候&#xff0c;并发量小&#xff0c;用户使用的少&#…

使用和制作动、静态库

文章目录什么是库&#xff1f;静态库打包方式使用方式生成并执行可执行程序粗暴方式优化方式动态库不一样的.o文件打包方式使用方式生成可执行程序运行可执行程序无法运行时的解决方案动静态库与动静态链接什么是库&#xff1f; 从一开始的helloworld&#xff0c;到现在熟练使…

SpringBoot项目中日志控制,配置logback(logback.xml的配置及介绍)

SpringBoot项目中日志控制&#xff0c;配置logback&#xff08;logback.xml的配置及介绍&#xff09;前言一、大致介绍logback依赖jar包logback的默认配置创建logback.xml配置文件仰天大笑出门去&#xff0c;我辈岂是蓬蒿人前言 SpringBoot项目中对日志的处理手动控制&#xf…

从 JavaScript 中的数组中删除空对象

从数组中删除空对象&#xff1a; 使用 Array.filter() 方法遍历数组。将每个对象传递给 Object.keys() 方法并检查键的长度是否不等于 0。filter 方法将返回一个不包含空对象的新数组。 const arr [{}, {id: 1}, {}, {id: 2}, {}];const results arr.filter(element > {…

scrum看板视图切换时间线视图做项目管理

企业需要开发一个项目&#xff0c;可以制作时间线进行管理&#xff0c;以便参与者和管理者了解项目的时间进度。项目进行到哪一步&#xff0c;参与者有哪些&#xff0c;责任人是谁&#xff0c;这些都可以通过时间线进行展示。「时间线视图」是一种比甘特图更轻量、更实用的工具…

Chapter6:机器人SLAM与自主导航

ROS1{\rm ROS1}ROS1的基础及应用&#xff0c;基于古月的课&#xff0c;各位可以去看&#xff0c;基于hawkbot{\rm hawkbot}hawkbot机器人进行实际操作。 ROS{\rm ROS}ROS版本&#xff1a;ROS1{\rm ROS1}ROS1的Melodic{\rm Melodic}Melodic&#xff1b;实际机器人&#xff1a;Ha…

【Spring Cloud Alibaba】001-单体架构与微服务架构

【Spring Cloud Alibaba】001-单体架构与微服务 文章目录【Spring Cloud Alibaba】001-单体架构与微服务一、单体架构1、单体应用与单体架构2、单体应用架构图3、单体架构优缺点优点缺点二、微服务1、微服务的“定义”2、微服务的特性3、微服务架构图4、微服务的优缺点优点缺点…

Python自动批量修改文件名称的方法大全

前言本文介绍基于Python语言&#xff0c;按照一定命名规则批量修改多个文件的文件名的方法。已知现有一个文件夹&#xff0c;其中包括班级所有同学上交的作业文件&#xff0c;每人一份&#xff1b;所有作业文件命名格式统一&#xff0c;都是地信1701_姓名_学习心得格式。现需要…

论文解读:(TransA)TransA: An Adaptive Approach for Knowledge Graph Embedding

简介 先前的知识表示方法&#xff1a;TransE、TransH、TransR、TransD、TranSparse等。的损失函数仅单纯的考虑hrh rhr和ttt在某个语义空间的欧氏距离&#xff0c;认为只要欧式距离最小&#xff0c;就认为h和th和th和t的关系为r。显然这种度量指标过于简单&#xff0c;虽然先…

榜上有名丨创新微MinewSemi荣登“物联之星”投资价值榜和创新产品榜

春风送暖&#xff0c;喜讯连连&#xff01;2023年2月7日&#xff0c;“2022物联之星”中国物联网产业年度榜单评选结果正式公布。经过层层评选&#xff0c;深圳创新微技术有限公司有幸在本届物联之星大奖中&#xff0c;荣获2022“物联之星”年度榜单之中国物联网企业投资价值50…

信号完整性设计规则之单根信号失真最小化

本文内容从《信号完整性与电源完整性分析》整理而来&#xff0c;加入了自己的理解&#xff0c;如有错误&#xff0c;欢迎批评指正。 1. 通常采用所能容许的最长上升边。 上升边越短&#xff0c;带宽越大&#xff0c;信号完整性问题越严重。 2. 使用可控阻抗走线。 可控阻抗…

硬件_IMX6ULL的LCD控制器

硬件_IMX6ULL的LCD控制器 文章目录硬件_IMX6ULL的LCD控制器一、 LCD控制器模块介绍1.1 硬件框图1.2 数据传输与处理1.3 时序控制二、 LCD控制器寄存器简介2.1 LCDIF_CTRL寄存器2.2 LCDIF_CTRL1寄存器2.3 LCDIF_TRANSFER_COUNT寄存器2.4 LCDIF_VDCTRL0寄存器2.5 LCDIF_VDCTRL1寄…

基础篇—一文掌握css的边框属性

CSS 边框属性 CSS边框属性允许你指定一个元素边框的样式和颜色。 1、边框样式 边框样式属性指定要显示什么样的边界。 border-style属性用来定义边框的样式 2、边框宽度 您可以通过 border-width 属性为边框指定宽度。 为边框指定宽度有两种方法:可以指定长度值,比如 2px…

检查nmos管是否损坏

NCEP85T14 功率mos管为例 以NMOS举例&#xff0c;只用万用表二极管档测量MOS管的好坏-电子发烧友网 NMOS的D极和S极之间有一个寄生二极管&#xff0c;方向为S到D&#xff0c;利用二极管单向导电性以及MOS管导通时寄生二极管截止的特性&#xff0c;可以快速测量MOS好坏。 1、测…

搭建Hexo博客-第2章-Hexo基本用法

搭建Hexo博客-第2章-Hexo基本用法 搭建Hexo博客-第2章-Hexo基本用法 搭建Hexo博客-第2章-Hexo基本用法 大家好&#xff0c;在上一篇文章中&#xff0c;我们学习了 Git 、GitHub 和 Coding 的基本用法&#xff0c;在这一节中&#xff0c;我将介绍 Hexo 的基本用法。阅读完这篇…

举个栗子~Tableau 技巧(251):统一多个工作表的坐标轴范围

在工作汇报场景&#xff0c;有一个很常见、很多数据粉反馈的需求&#xff1a;同一看板上的两个图表&#xff0c;因为轴范围不一致&#xff08;如下图&#xff09;&#xff0c;很难直观比较。有什么办法可以统一它们的坐标轴范围呢&#xff1f; 类似需求&#xff0c;不论两个还是…

SpringCloud学习笔记 - @SentinelResource的fallbackblockHandler配置详解 - sentinel

1. sentinel服务负载均衡测试 sentinel默认开启了负载均衡的轮询模式&#xff0c;为了测试sentinel服务负载均衡的效果&#xff0c;需要先创建两个服务提供者和一个服务消费者。 1.1. 分别创建两个服务提供者-支付服务9003、9004 1. 添加pom依赖&#xff1a; 提供者只需要将…

ElementUI中为什么使用this.$refs.form.validate验证成功却直接跳过

ElementUI中为什么使用this.$refs.form.validate验证成功却直接跳过 问题背景 在写一个Vue练手项目时&#xff0c;我使用rulse对表单中用户输入的数据进行校验&#xff0c;但莫名奇妙就发现&#xff1a;当我点击提交表单时&#xff0c;表单中的数据都验证成功了&#xff0c;但是…

SpringBoot分页实现

简介 分页功能是一个简单但必需的功能&#xff0c;在 SpringBoot 中分页实现非常的简单&#xff0c;有多种实现方式&#xff1b;主要和项目集成的持久层框架有关&#xff1b;这里主要介绍集成 MyBatis 和 SpringDataJpa 的分页实现 Mybatis - 使用 PageHelper 分页 首先在 p…