热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

42linux内核里的输入子系统分析

linux里的子系统:linux内核里把某种功能类型的源码划分成一个源码模块,也就是把一类相关的源文件集中起来封装出的功能模块.如内核源码目录下”driversinput”里就

linux里的子系统: linux内核里把某种功能类型的源码划分成一个源码模块, 也就是把一类相关的源文件集中起来封装出的功能模块. 如内核源码目录下”drivers/input”里就是输入子系统的源码, “drivers/i2c”就是i2c子系统.

///////////
输入子系统的主要入口在”drivers/input/input.c”源文件:

static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
.llseek = noop_llseek,
};

static int __init input_init(void)
{
...
err = register_chrdev(INPUT_MAJOR, "input", &input_fops); //当用户程序操作"/dev/input/event*"设备文件时,首先会用到input_fops里的input_open_file函数.
...
};
subsys_initcall(input_init); //子系统初始化


static int input_open_file(struct inode *inode, struct file *file)
{
struct input_handler *handler; //表示一种输入设备对用户程序的接口, 也就是这种接口提供input_event数据到用户进程. 内核里有input_handler的对象evdev_handler(最常用), joydev_handler(手柄类设备), mousedev_handler(鼠标类设备).
// 通常情况下输入设备驱动使用的都是evdev_handler, 它可支持键盘,鼠标,触摸屏等输入设备。产生的设备文件为event*. 内核提供的input_handler对象都已经实现好file_operations里的功能函数, 我们的设备驱动只要提供数据给handler对象, 用户进程即可通过调用handler对象获取设备驱动的数据.


const struct file_operations *old_fops, *new_fops = NULL;

...
handler = input_table[iminor(inode) >> 5];
if (handler)
new_fops = fops_get(handler->fops);

...
old_fops = file->f_op;
file->f_op = new_fops; //像misc子系统一样,更换文件描述符的file_operations对象。更换后,用户调用read, write这此操作时就会调用new_fops里的功能函数

err = new_fops->open(inode, file);
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
...
}

////////////////////
“drivers/input/evdev.c”可看出, handler对象已实现好用户程序的调用接口功能函数.

static const struct file_operations evdev_fops = {
.owner = THIS_MODULE,
.read = evdev_read,
.write = evdev_write,
.poll = evdev_poll,
.open = evdev_open,
.release = evdev_release,
.unlocked_ioctl = evdev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = evdev_ioctl_compat,
#endif
.fasync = evdev_fasync,
.flush = evdev_flush,
.llseek = no_llseek,
};

static struct input_handler evdev_handler = {
.event = evdev_event, //输入设备驱动里调用input_report..., input_sync这些函数时就是调用handler的evdev_event函数
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};

static int __init evdev_init(void)
{
return input_register_handler(&evdev_handler); //handler对象注册时,会加入input_handler_list链表里
}

/////////////////
输入设备注册时,内核会让输入设备与handler对象进行匹配, 确定输入设备使用哪个handler对象的接口.

int input_register_device(struct input_dev *dev)
{
...
/* Every input device generates EV_SYN/SYN_REPORT events. */
__set_bit(EV_SYN, dev->evbit);

...

list_add_tail(&dev->node, &input_dev_list); //注册输入设备时会加入设备链表input_dev_list;

list_for_each_entry(handler, &input_handler_list, node) //遍历handler对象的链表
input_attach_handler(dev, handler); //进行匹配

...
}

输入子系统是linux内核里设备驱动分层思想的一个应用.

我们写的输入设备驱动里只需要实现好硬件部分的功能,再根据硬件的状态提交数据就可以了。不同的输入设备硬件,意味着需要不同的输入设备驱动来实现. 但在linux内核里,用户程序获取输入设备数据的接口都是统一的,标准的接口(struct input_event数据), 所以在内核里把这接口(struct input_handler)独立起来, 供所有输入设备驱动实现数据转交到用户进程.


推荐阅读
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 深入理解Tornado模板系统
    本文详细介绍了Tornado框架中模板系统的使用方法。Tornado自带的轻量级、高效且灵活的模板语言位于tornado.template模块,支持嵌入Python代码片段,帮助开发者快速构建动态网页。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • andr ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
author-avatar
jgfioirejmf
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有