当前位置: 首页 > news >正文

驱动开发,IO多路复用实现过程,epoll方式

1.框架图

被称为当前时代最好用的io多路复用方式;

核心操作:一棵树(红黑树)、一张表(内核链表)以及三个接口;

 思想:(fd代表文件描述符)

        epoll要把检测的事件fd挂载到内核空间红黑树上,遍历红黑树,调用每个fd对应的操作方法,找到发生事件的fd,如果没有发生事件的fd,进程休眠,如果事件发生,将发生事件的fd拷贝一份放到内核链表,每个节点对应一个fd,最后把链表的节点信息传递到用户空间的数组中,用户空间无需判断事件的发生,需要判断事件类型(读写等);

 

2.代码

---pro1.c---应用程序(epoll方式)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/epoll.h>int main(int argc, const char *argv[])
{int fd1,fd2,epfd;char buf[128] = {0};struct epoll_event event;  //用于操作epollstruct epoll_event events[10];  //用户空间存放发生事件的数组//创建epoll句柄,红黑树根节点epfd = epoll_create(1);if(epfd < 0){printf("epoll_create fail\n");exit(-1);}//打开设备文件fd1 = open("/dev/input/mouse0", O_RDWR);if (fd1 < 0){printf("鼠标事件文件失败\n");exit(-1);}fd2 = open("/dev/myled0", O_RDWR);if (fd2 < 0){printf("自定义事件文件失败\n");exit(-1);}//添加准备就绪事件到epollevent.events = EPOLLIN;  //读事件event.data.fd = fd1;if((epoll_ctl(epfd,EPOLL_CTL_ADD,fd1,&event)) < 0){printf("epoll_ctl fd1 fail\n");}event.events = EPOLLIN;  //读事件event.data.fd = fd2;if((epoll_ctl(epfd,EPOLL_CTL_ADD,fd2,&event)) < 0){printf("epoll_ctl fd2 fail\n");}//监听时间是否发生while(1){//成功接收返回时间的个数,放入events数组中int ret = epoll_wait(epfd,events,10,-1);if(ret < 0){printf("epoll_wait fail\n");exit(-1);   }int i;//循环遍历数组,做事件的处理for(i=0; i<ret; i++){if(events[i].events & EPOLLIN)  //发生事件是读事件{read(events[i].data.fd,buf,sizeof(buf));printf("buf:%s\n",buf);memset(buf,0,sizeof(buf));}}}close(fd1);close(fd2);return 0;
}
---pro2.c---应用程序(模拟自定义设备数据就绪)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>int main(int argc, const char *argv[])
{char buf[128] = "hello world";int fd = open("/dev/myled0", O_RDWR);if (fd < 0){printf("打开设备文件失败\n");exit(-1);}write(fd, buf, sizeof(buf));close(fd);return 0;
}
---epoll.c---驱动程序

 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include<linux/poll.h>char kbuf[128] = {0};
unsigned int major;
struct class *cls;
struct device *dev;
unsigned int condition = 0;// 定义一个等待队列头
wait_queue_head_t wq_head;// 封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{int ret;ret = copy_to_user(ubuf, kbuf, size);if (ret){printk("copy_to_ user err\n");return -EIO;}condition = 0; // 下一次硬件数据没有就绪return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{int ret;// 从用户拷贝数据,模拟硬件数据ret = copy_from_user(kbuf, ubuf, size);if (ret){printk("copy_from_user err\n");return -EIO;}condition = 1;wake_up_interruptible(&wq_head);return 0;
}
//封装POLL方法
__poll_t mycdev_poll(struct file *file, struct poll_table_struct *wait)
{__poll_t mask = 0;//向上提交等待队列头poll_wait(file,&wq_head,wait);//根据事件是否发生给一个合适的返回值if(condition){mask = POLLIN;}return mask;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}struct file_operations fops = {.open = mycdev_open,.read = mycdev_read,.poll = mycdev_poll,.write = mycdev_write,.release = mycdev_close,
};// 入口函数
static int __init mycdev_init(void)
{//初始化等待队列init_waitqueue_head(&wq_head);major = register_chrdev(0, "myled", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n", major);// 向上提交目录cls = class_create(THIS_MODULE, "MYLED");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录成功\n");// 向上提交设备节点信息int i;for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);if (IS_ERR(dev)){printk("向上提交设备节点信息失败\n");return -PTR_ERR(dev);}}printk("向上提交设备节点信息成功\n");return 0;
}// 出口函数
static void __exit mycdev_exit(void)
{// 销毁设备节点信息int i;for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 销毁目录信息class_destroy(cls);// 字符设备驱动注销unregister_chrdev(major, "myled");
}// 声明
// 入口函数地址
module_init(mycdev_init);
// 出口函数地址
module_exit(mycdev_exit);
// 遵循的GPL协议
MODULE_LICENSE("GPL");

 

3.测试结果

 执行pro2.c,自定义事件被监听到;

 在ubuntu上动鼠标,鼠标事件被监听;

相关文章:

驱动开发,IO多路复用实现过程,epoll方式

1.框架图 被称为当前时代最好用的io多路复用方式&#xff1b; 核心操作&#xff1a;一棵树&#xff08;红黑树&#xff09;、一张表&#xff08;内核链表&#xff09;以及三个接口&#xff1b; 思想&#xff1a;&#xff08;fd代表文件描述符&#xff09; epoll要把检测的事件…...

java在mysql中查询内容无法塞入实体类中,报错 all elements are null

目录 一、问题描述二、解决方案 一、问题描述 java项目中整体配置了mysql的驼峰式字段匹配规则。 mybatis.configuration.map-underscore-to-camel-casetrue由于项目需求&#xff0c;需要返回字段为file_id&#xff0c;file_url&#xff0c;并且放入实体类中&#xff0c;实体…...

Linux 挂载

挂载需要挂载源和挂载点 虚拟机本身就有的挂源 添加硬件 重启虚拟机 操作程序 sudo fdisk -l //以管理员权限查看电脑硬盘使用情况sudo mkfs.ext4 /dev/sdb //以管理员身份格式化硬盘sudo mkdir guazai //创建挂载文件夹 sudo mount /dev/sdb/guazai //将挂载源接上挂载点 s…...

[面试] 15道最典型的k8s面试题

文章目录 在 Kubernetes 中&#xff0c;有以下常见的资源对象&#xff1a;1.什么是 Kubernetes&#xff1f;它的主要特点是什么&#xff1f;2. Kubernetes 中的 Pod 是什么&#xff1f;它的作用是什么&#xff1f;3.Kubernetes 中的 Deployment 和 StatefulSet 有何区别&#x…...

lintcode 552 · 创建最大数 【算法 数组 贪心 hard】

题目 https://www.lintcode.com/problem/552/description 描述 给出两个长度分别是m和n的数组来表示两个大整数&#xff0c;数组的每个元素都是数字0-9。从这两个数组当中选出k个数字来创建一个最大数&#xff0c;其中k满足k < m n。选出来的数字在创建的最大数里面的位置…...

ModbusTCP服务端

1在Device下&#xff0c;添加设备net&#xff1a; 公交车。 2在net下添加 ModbusTCP...

Middleware ❀ Hadoop功能与使用详解(HDFS+YARN)

文章目录 1、服务概述1.1 HDFS1.1.1 架构解析1.1.1.1 Block 数据块1.1.1.2 NameNode 名称节点1.1.1.3 Secondary NameNode 第二名称节点1.1.1.4 DataNode 数据节点1.1.1.5 Block Caching 块缓存1.1.1.6 HDFS Federation 联邦1.1.1.7 Rack Awareness 机架感知 1.1.2 读写操作与可…...

Matlab图像处理-从RGB转换为HSV

从RGB转换为HSV HSV彩色系统基于圆柱坐标系。从RGB转换为HSV需要开发将(笛卡儿坐标系中的)RGB值映射到圆柱坐标系的公式。多数计算机图形学教材中已详细推导了这一公式&#xff0c;故此处从略。 从RGB转换为HSV的MATLAB函数是rgb2hsv&#xff0c;其语法为&#xff1a; hsv_imag…...

iOS Error Domain=PHPhotosErrorDomain Code=3300

AVCapturePhoto的数据保存到 PHPhotoLibrary的时候报错Error DomainPHPhotosErrorDomain Code3300解决代码&#xff08;也可以使用addResourceWithType:data:options:来添加数据到request&#xff0c;JEPG的实测可以&#xff0c;raw的不确定&#xff09;&#xff1a; [PHPhoto…...

LeetCode(力扣)435. 无重叠区间Python

LeetCode435. 无重叠区间 题目链接代码 题目链接 https://leetcode.cn/problems/non-overlapping-intervals/ 代码 class Solution:def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:if not intervals:return 0intervals.sort(keylambda x: x[0])co…...

opencv c++实现鼠标框选区域并显示选择的图片区域

OpenCV可以使用setMouseCallback设置鼠标事件的回调函数,从而然后根据需要进行处理。 setMouseCallback原型为: void cv::setMouseCallback(const cv::String& windowName, MouseCallback onMouse, void* userData = 0); 其中,参数说明如下:windowName:窗口名称 onMo…...

Python实现自主售卖机

1 问题 在python中我们常常使用到条件判断&#xff0c;if语句时常见的条件判断语句之一。那么如何使用if语句实现根据情况自动选择商品进行售卖呢&#xff1f; 2 方法 根据if语句执行时从上往下执行的特点&#xff0c;使用if语句、dict和list来实现整个流程。 代码清单 1 drink…...

任务复杂度与人机

任务复杂度计算是指根据任务的难易程度和需要的资源投入来评估任务的复杂程度。一般来说&#xff0c;任务复杂度计算会考虑以下几个因素&#xff1a; 难度程度&#xff1a;任务的难度程度是指完成任务所需要的知识、技能和经验等的要求。较高的难度程度会增加任务的复杂度。任务…...

Windows关闭zookeeper、rocketmq日志输出以及修改rocketmq的JVM内存占用大小

JDK-1.8zookeeper-3.4.14rocketmq-3.2.6 zookeeper 进入到zookeeper的conf目录 清空配置文件&#xff0c;只保留下面这一行。zookeeper关闭日志输出相对简单。 log4j.rootLoggerOFFrocketmq 进入到rocketmq的conf目录 logback_broker.xml <?xml version"1.0&q…...

Convai:让虚拟游戏角色更智能的对话AI人工智能平台

【产品介绍】​ 名称 Convai​ 具体描述​ Convai是一款专为虚拟世界而设计的对话人工智能平台&#xff0c;它可以让你为你的游戏或应用中的角色 赋予人类般的对话能力。Convai利用了最先进的生成式对话人工智能技术&#xff0c;让你的角色可以…...

【送书活动】大模型赛道如何实现华丽的弯道超车

文章目录 导读前言AI/ML 模型训练任务对数据平台的需求01 具备对海量小文件的频繁数据访问的 I/O 效率02 提高 GPU 利用率&#xff0c;降低成本并提高投资回报率03 支持各种存储系统的原生接口04 支持单云、混合云和多云部署 核心密码01 通过数据抽象化统一数据孤岛02 通过分布…...

opencv dnn模块 示例(16) 目标检测 object_detection 之 yolov4

博客【opencv dnn模块 示例(3) 目标检测 object_detection (2) YOLO object detection】 测试了yolov3 及之前系列的模型&#xff0c;有在博客【opencv dnn模块 示例(15) opencv4.2版本dnn支持cuda加速&#xff08;vs2015异常解决&#xff09;】 说明了如何使用dnn模块进行cuda…...

Python提取JSON数据中的键值对并保存为.csv文件

本文介绍基于Python&#xff0c;读取JSON文件数据&#xff0c;并将JSON文件中指定的键值对数据转换为.csv格式文件的方法。 在之前的文章Python提取JSON文件中的指定数据并保存在CSV或Excel表格文件内&#xff08;https://blog.csdn.net/zhebushibiaoshifu/article/details/132…...

使用IDEA开发Servlet

一、新建工程 二、填写新工程的基本信息 javaee8的项目可以运行在tomcat9 三、配置tomcat 1、编辑server信息 “On frame deactivation”的意思是idea窗口发生切换时。 2、编辑部署信息 war exploded方式&#xff0c;这种方式是以文件夹方式部署的&#xff0c;支持热加载。 …...

腾讯mini项目-【指标监控服务重构】2023-07-21

今日已办 当在Docker容器中运行程序时&#xff0c;可能会遇到使用os.Getpid()函数时出现异常的情况。这是因为Docker容器中的进程隔离机制与宿主机器不同&#xff0c;容器内部的进程可能无法访问宿主机器的进程信息。 要解决这个问题&#xff0c;可以尝试&#xff1a; 使用do…...

Spring MVC里的DispatchServlet(结合Spring官网翻译)

Spring MVC里的DispatchServlet 前言1.Spring Web MVC1.1 DispatcherServlet&#xff08;中央调度器&#xff09;1.1.1 Context Hierarchy&#xff08;上下文层次结构&#xff09;1.1.2 Special Bean Types&#xff08;特定的bean类型&#xff09;1.1.3 Web MVC Config1.1.4 Se…...

数据分享|R语言武汉流动人口趋势预测:灰色模型GM(1,1)、ARIMA时间序列、logistic逻辑回归模型...

全文链接&#xff1a;http://tecdat.cn/?p32496 人口流动与迁移&#xff0c;作为人类产生以来就存在的一种社会现象&#xff0c;伴随着人类文明的不断进步从未间断&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 相关视频 人力资源是社会文明进步、人民富裕…...

解决 Axios 跨域问题,轻松实现接口调用

跨域是指访问另外一个域的资源&#xff0c;由于浏览器的同源策略&#xff0c;默认情况下使用 XMLHttpRequest 和 Fetch 请求时是不允许跨域的。跨域的根本原因是浏览器的同源策略&#xff0c;这是由浏览器对 JavaScript 施加的安全限制。 Axios 跨域常见报错 跨域请求被阻止 (…...

Layui快速入门之第十节 表单

目录 一&#xff1a;基本用法 二&#xff1a;输入框 普通输入框 输入框点缀 前置和后置 前缀和后缀 动态点缀 密码显隐 内容清除 自定义动态点缀 点缀事件 三&#xff1a;复选框 默认风格 标签风格 开关风格 复选框事件 四&#xff1a;单选框 普通单选框 自…...

Linux之yum/git的使用

目录 一、yum 1、关于yum 2、yum的操作 ①、yum list ②、yum install ③、yum remove 二、git 1、Linux中连接gitee 2、git的操作 ①git add [文件] ②git commit -m "提交日志" ③git push 3、可能出现的问题 ①配置用户名、邮箱 ②出现提交冲突 ③…...

使用ExcelJS快速处理Node.js爬虫数据

什么是ExcelJS ExcelJS是一个用于处理Excel文件的JavaScript库。它可以让你使用JavaScript创建、读取和修改Excel文件。 以下是ExcelJS的一些主要特点&#xff1a; 支持xlsx、xlsm、xlsb、xls格式的Excel文件。可以创建和修改工作表、单元格、行和列。可以设置单元格样式、字…...

轻量级的Python IDE —— Thonny

现在的开发工具太多了&#xff0c;而且每个开发工具都致力于做成最好用最智能的工具&#xff0c;所以功能越堆越多&#xff0c;越怼越智能。安装这些开发工具比较烧脑&#xff0c;经常需要经过许多配置步骤。作为一个 Python 开发者来说&#xff0c;好多人光是这些配置都要弄半…...

java设计模式之观察者模式

. 基本概念 观察者&#xff08;Observer&#xff09;模式中包含两种对象&#xff0c;分别是目标对象和观察者对象。在目标对象和观察者对象间存在着一种一对多的对应关系&#xff0c;当这个目标对象的状态发生变化时&#xff0c;所有依赖于它的观察者对象都会得到通知并执行它…...

掌动智能分享:性能压力测试的重要性与优势

在当今数字化时代&#xff0c;应用程序的性能对于用户体验和业务成功至关重要。为了保证应用程序的高性能和稳定性&#xff0c;性能压力测试成为了不可或缺的环节。在这个领域&#xff0c;掌动智能作为一家专业的性能压力测试公司&#xff0c;正以其卓越的技术与服务&#xff0…...

C# ppt文件转换为pdf文件

使用第三方插件 Office 实现转换 1.Application方式转换 /// <summary>/// Microsoft.Office.Interop.PowerPoint/// 使用第三方软件 office/// </summary>/// <param name"pptPath">需要转换的ppt文件路径</param>/// <param name"…...

做网站要不要签合同/互联网营销师是干什么的

12、请描述OSI7层模型各层名字及功能&#xff0c;并举例在不同层对应的协议 第一层&#xff1a;物理层&#xff0c;利用传输介质为数据提供物理连接&#xff0c; 对应的协议&#xff1a;ARP 第二层&#xff1a;数据链路层&#xff1a;建立和管理各节点间的链接链路 对应的协议&…...

青岛做网站哪家优化好/seo优化价格

点击上方“程序IT圈”&#xff0c;选择“置顶公众号”每天早晨8点50分&#xff0c;准点开车打卡本文来源于破产女中年&#xff0c;真实故事老公失业第二个月&#xff0c;银行卖我的p2p爆雷了01小城无新事我家在安徽北部的一个县城。年少时想过各种奋斗&#xff0c;却在父母不忍…...

不知此网站枉做男人/沈阳企业网站seo公司

设备树的历史 1、kernel最早加入设备树的历史得追溯到v2.6.23&#xff0c;从这个版本开始&#xff0c;在driver目录下多了一个of目录。当然&#xff0c;此时只是引入一些新想法而已。这距离linus大怒说出(2011年3月17日)&#xff1a;this whole ARM thing is a f*cking pain in…...

傻瓜式网站建设/营销软文范例大全100字

转载 Nginx作为反向代理并以HTTP协议反向代理HTTPS服务 - 互联网科技 - 亿速云 这篇文章主要介绍“Nginx作为反向代理并以HTTP协议反向代理HTTPS服务”&#xff0c;在日常操作中&#xff0c;相信很多人在Nginx作为反向代理并以HTTP协议反向代理HTTPS服务问题上存在疑惑&#x…...

工商网站如何做企业增资/北京网站优化怎么样

一 故障现象&#xff1a;硬盘灯告警二 故障分析&#xff1a;硬盘fault三 处理过程&#xff1a;现场查看发现主机配置两块300GB硬盘&#xff0c;且系统正常运行。判断主机应该做了riad 1&#xff08;fdisk -l命令显示逻辑盘的大小为300GB&#xff09;在线更换硬盘more /var/log/…...

宜春网站制作/网络推广赚钱平台有哪些

工控机安装 openvino2021.4 需要安装python 就安装了python3.8.8 但是直接报错 安装不上去 在网上找了各种方法&#xff0c;最后安装了KB2533623 之后可以安装python了 下载地址 链接: https://pan.baidu.com/s/15KpcRN2w5v7xQtaFm7JlMw?pwdaxs6 提取码: axs6 或者 KB25…...