Linux驱动学习之内核poll阻塞

ops/2024/9/20 7:17:09/ 标签: linux, 学习, 运维

linux系统编程课程中学习过多路IO复用,简单来说就三个函数select,poll,epoll。

对于select

        此函数是跨平台的,可以在windows,Linux中使用。

对于poll与epoll

        只能在linux平台下使用,

        epoll底层实现是一个红黑树,效率高,检测的文件更多。

这三个函数可以实现并发。

前面的章节中讲了,等待队列用于内核与上层的数据同步,现在我们来实现内核poll与上层的数据同步。

通过前面我们知道,内核驱动中,如果read函数中没有阻塞,上层read就没有阻塞,可是在linux系统编程课中,明明学习的read函数是阻塞的,这里可以大胆的猜测,系统编程实在别人写好的驱动上运行的,他内核驱动内部实现了read的阻塞。

本章学习内核poll机制,学完对理解linux系统编程多路io复用有很大帮助。

  • 内核poll的实现

在文件操作结构体中有一个poll函数,我们实现这个函数,并在这个函数中实现阻塞,那么上层调用这个函数就会调用上册函数阻塞。

那么poll阻塞是怎么实现的呢。

  • poll阻塞的实现
  1. 在poll函数里调用 poll_wait()函数。
  2. 在合适的情况下返回合适的值。

当然内核poll阻塞是靠等待队列实现的,所以,要在需要地方唤醒。

  • API函数
 void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{

参数1:poll函数的第一个参数,

参数2:等待队列地址

参数3:poll函数第二个参数

  • 整体实现

在其他地方调用,并设置cond=1;当然也得在别的地方把cond变为0,不然就只在开头阻塞一次

  • 读取按键整体代码
#include "linux/cdev.h"
#include "linux/device.h"
#include "linux/device/class.h"
#include "linux/poll.h"
#include "linux/export.h"
#include "linux/fs.h"
#include "linux/gpio.h"
#include "linux/interrupt.h"
#include "linux/irq.h"
#include "linux/module.h"
#include "linux/of_device.h"
#include "linux/of_gpio.h"
#include "linux/platform_device.h"
#include "linux/poll.h"
#include "linux/printk.h"
#include "linux/timer.h"
#include "linux/types.h"
#include "linux/uaccess.h"
#include "linux/wait.h"
#include "linux/zconf.h"
uint32_t pin;
dev_t dev_num;
struct cdev *cdev;
struct class *cls;
struct device * dev;
uint8_t cond;
struct timer_list timer;DECLARE_WAIT_QUEUE_HEAD(queue);
uint8_t val;
irqreturn_t fun(int i, void * a)
{val=gpio_get_value(pin);printk("%d\r\n",val);mod_timer(&timer, jiffies+msecs_to_jiffies(10));return 0;
}
static ssize_t read(struct file *f, char __user *b, size_t s, loff_t *offt)
{cond=0;// wait_event_interruptible(queue,cond);int a=copy_to_user(b,&val,1);if(a){}return 0;
}
static int open(struct inode *i, struct file *f)
{int ret=devm_request_irq(dev, gpio_to_irq(pin),fun,IRQ_TYPE_EDGE_FALLING,"key", NULL);printk("%d\r\n",ret);return ret;
}
static int close(struct inode *i, struct file *f)
{devm_free_irq(dev,gpio_to_irq(pin),NULL);return 0;
}
__poll_t poll (struct file *f, struct poll_table_struct *p)
{poll_wait(f, &queue, p);if(cond==1){return EPOLLIN;}return 0;
}
struct file_operations fops={.owner=THIS_MODULE,.read=read,.open=open,.release=close,.poll=poll,
};
void func(struct timer_list *tl)
{wake_up_interruptible(&queue);cond=1;
}
int probe(struct platform_device *d)
{timer_setup(&timer, func, 0);dev=&d->dev;pin=of_get_named_gpio(d->dev.of_node,"key_pin",0);printk("%d\r\n",pin);printk("%d\r\n", platform_get_irq(d,0));printk("irq_num=%d", gpio_to_irq(pin));gpio_request(pin,"key");gpio_direction_input(pin);// devm_request_irq(&d->dev, gpio_to_irq(pin),fun,IRQ_TYPE_EDGE_FALLING,"key", NULL);alloc_chrdev_region(&dev_num, 0, 1,"key");cdev=cdev_alloc();cdev->ops=&fops;cdev_add(cdev,dev_num,1);cls=class_create(THIS_MODULE, "key");device_create(cls, NULL,dev_num,NULL,"key");return 0;
}
int remove(struct platform_device *d)
{return 0;
}
static struct of_device_id match={.compatible="key",
};static struct platform_driver driver={.probe=probe,.remove=remove,.driver={.name="key",.of_match_table=&match,},
};
static int __init start(void)
{platform_driver_register(&driver);printk(KERN_INFO "Hello, world!\n");return 0;
}
static void __exit stop(void)
{platform_driver_unregister(&driver);printk(KERN_INFO "Goodbye, world!\n");
}
module_init(start);
module_exit(stop);
MODULE_LICENSE("GPL");

 补充,上面列子只在poll中实现阻塞,当然也可以自己增加逻辑让在read和epoll中都阻塞,就能实现在系统编程中,多路io复用让夜歌poll监控所有文件描述符,当不用多路io复用,read照样阻塞。


http://www.ppmy.cn/ops/100617.html

相关文章

WebSocket、Socket和Netty的关系

目录 WebSocket、Socket和Netty的关系 WebSocket Socket Netty 关系总结 Socket API 有那些? 1. socket() 2. bind() 3. listen() 4. accept() 5. connect() 6. send() 和 recv() 7. close() 8. shutdown() 9. inet_pton() 和 inet_ntop() 10. setso…

Windows系统安装MySQL

下载MySQL 打开网址MySQL :: Download MySQL Community Server点击图下所示位置Download 进入图下所示界面,点击图下所示位置不登录下载 已下载完成 安装MySQL 将下载好的压缩包解压到一个专门的位置,该软件为绿色版软件,解压即可使用 配置…

Spring 中的BeanPostProcessor

BeanPostProcessor 是 Spring Framework 中的一个接口,用于对 bean 实例进行自定义处理,它位于 org.springframework.beans.factory.config 包下。该接口允许开发者在 Spring 容器创建 bean 实例后进行处理,或在 bean 实例初始化过程中进行自…

单调栈 LeetCode 1130. 叶值的最小代价生成树

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 给你一个正整数数组 arr,考虑所有满足以下条件的二叉树: 每个节点都有 0 个或是 2 个子节点。数…

论坛系统登录测试结果

目录 1 登录成功1.1 输入合法已注册手机号 2 登录失败2.1 输入未注册手机号2.2 输入非法手机号2.3 输入错误、过期验证码 论坛系统——部分测试用例 1 登录成功 1.1 输入合法已注册手机号 打开登录界面 输入已注册手机号 点击发送验证码 输入验证码,点击登录按钮 …

架构师面试题系列之Spring MVC面试专题及答案(31题)

目录 1、什么是 SpringMvc?说一下你对它的理解2、SpringMVC 的优点 :3、SpringMVC 工作原理?4、SpringMVC 的主要组件?5、讲下 SpringMvc 的执行流程6、SpingMvc 中的控制器的注解一般用那个,有没有别的注解可以替代?7、如果在拦截请求中,想拦截 get 方式提交的方法,怎么…

Python接口自动化测试:断言封装详解

在进行API接口测试时,断言起着至关重要的作用。断言是用于验证预期结果与实际结果是否一致的过程。在Python中,我们可以利用一些库来实现断言功能。 1. 安装必要的库 在Python中,我们主要会使用两个库:requests和jsonpath。requ…

解析阿里巴巴中国站商品详情API返回值的更新与变化

阿里巴巴中国站(通常指的是1688.com,阿里巴巴的国内批发平台)的商品详情API返回值可能会随着平台功能的更新、数据结构的调整或API版本的迭代而发生变化。为了准确解析这些更新与变化,你可以采取以下几个步骤: 1. 查阅…

2024焊工操作证考试在线模拟考试题

焊工证考试试题分为理论《焊工理论知识》考试和《焊工实操知识》专业能力考核。 焊工证考试试题理论知识考试采用闭卷电脑答题方式;理论知识考试和实操考核均实行百分制,焊工证考试成绩皆达80分及以上者为合格。 以下为焊工理论考试模拟试题&#xff0c…

apache httpclient速成

目录标题 快速使用连接池参数连接池状态清除闲置连接evictIdleConnections删除过期连接 timeToLive 和evictExpiredConnections 注意释放内存关闭流 http和netty的关系 导入依赖 <dependency><groupId>org.apache.httpcomponents.client5</groupId><artif…

QT通过信号传递参数至槽函数(不通层级通信)

传递参数参数多个&#xff0c;采用map&#xff0c;一直insert 前提&#xff0c; //map类型 typedef QMap <unsigned int , QByteArray> Map;//信号和槽的声明 signals:void sigToCems(InfoMap);void slotFromEms(Map Map);// 发射点&#xff1a;由事件触发 //Addr_EM…

龙旭 付玲云新歌推出原创歌曲热榜

盘点2024年8月全国受关注的经典热门歌曲你更爱那首&#xff1f; 歌曲1.《甜妹专属BGMentertainer》&#xff0c;2.情歌专属《尘世情缘》情歌唱给谁来听&#xff0c;3.巜迟来的情话》听完敢不敢留下你最想对TA说的话如果在18我没能送你花&#xff0c;那到28我请你喝酒吧&#x…

Linux驱动开发—设备模型框架 kobject创建属性文件

文章目录 什么是属性文件&#xff1f;1. sysfs 与 kobject2. 属性文件的作用3. 属性文件的基本操作4. 典型的属性文件用例5. 创建属性文件的步骤6.示例代码7.效果图 使用 ATTR 宏定义优化__ATTR用法解析1. __ATTR() 宏的定义2. __ATTR() 宏的参数3.优化示例 优化关键点解析1. 数…

Java与C#在中国:我们在信息技术领域的脆弱性和依赖性

2019年8月&#xff0c;微软公司宣布停止在俄罗斯销售新产品和服务&#xff0c;并暂停相关更新和授权。这一决定对俄罗斯用户和企业造成了不小的冲击。 2024年6月&#xff0c;微软陆续关闭中国线下门店授权。微软官方给出的回应是&#xff1a;为了满足客户不断变化的需求&#…

linux命令使用

vi可打开&#xff0c;可创建&#xff0c;cat只能打开已有的文件 rm -r 删除文件夹-r&#xff1a;这个选项代表“递归”&#xff08;recursive&#xff09;。当你用 -r 选项与 rm 一起使用时&#xff0c;rm 会递归地删除目录及其内容&#xff0c;包括所有子目录和文件。 pip i…

并行程序设计基础——MPI不连续数据发送(1)

目录 一、派生数据类型 二、定义新数据类型 1、连续复制的类型生成 2、向量数据类型的生成 3、索引数据类型的生成 4、结构数据类型的生成 5、新类型递交和释放 前面各节介绍的MPI程序设计都是发送或接收连续的数据,其实MPI还可以处理不连续的数据,基本方法有…

Linux 搜索历史命令Ctrl+R

最近使用CtrlR来搜索历史命令&#xff0c;对比速度比history 快一下&#xff0c;且看起来高级。记录如下&#xff1a;命令1&#xff1a;history 功能&#xff1a;显示当前Linux终端输入过的历史命令。案例&#xff1a;使用history 出来的结果很多&#xff0c;通常和grep 过滤&a…

如何根据域名选择合适的SSL证书

SSL证书是一种用于安全传输数据的数字证书。它通过加密数据&#xff0c;确保用户在与网站进行通信时信息得到保护。 有SSL证书和没有SSL证书证书的区别是什么&#xff1f; SSL证书配置前后比较直观的区别就是安全标识&#xff0c;SSL证书在浏览器地址栏显示一个小锁标志&#…

【Java】—— Java面向对象基础:定义圆类与通过对象传递参数

在Java编程中&#xff0c;我们可以创建多个类来组织和管理代码。在这个例子中&#xff0c;我们将创建一个Circle类和一个PassObject类。Circle类包含一个double型的radius属性和一个findArea()方法&#xff0c;用于计算圆的面积。PassObject类包含一个printAreas()方法&#xf…

Java 输入与输出之 NIO【非阻塞式IO】【NIO网络编程】探索之【二】

上一篇博客我们介绍了NIO的核心原理、FileChannel和Buffer, 对Buffer的用法有了清晰的了解。上篇博客&#xff1a; Java 输入与输出之 NIO【非阻塞式IO】【NIO核心原理】探索之【一】 本篇博客我们将继续来探索NIO&#xff0c;介绍如何使用SocketChannel和ServerSocketChannel来…