Linux驱动学习之内核poll阻塞

news2024/12/26 21:24:05

在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.coloradmin.cn/o/2080497.html

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

相关文章

ArcGIS应用指南:近邻分析(点匹配到最近线段上)

近邻分析通常用于确定一个要素集中的要素与另一个要素集中最近要素的距离。当涉及到点匹配到最近的线时,这种分析可以用来确定每个点到最近线段的距离及位置,也就是我们常说的点匹配到最近线上,可以参考官方文档:近邻分析 (Covera…

EmguCV学习笔记 VB.Net 6.S 特别示例

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

深度学习基础(Datawhale X 李宏毅苹果书AI夏令营)

深度学习基础(Datawhale X 李宏毅苹果书AI夏令营) 3.1局部极小值和鞍点 3.1.1. 优化失败问题 在神经网络中,当优化到梯度为0的地方,梯度下降就无法继续更新参数了,训练也就停下来了,如图: 梯度为0的情况包含很多种情…

Anaconda3简介与安装步骤

目录 Anaconda3简介与功能 1.Anaconda3简介 2.主要功能和特点 3.使用场景 4.总结 Anaconda3安装 1.Anaconda3下载 1.1我的百度网盘 1.2官网下载 1.2.1访问官网 1.2.2输入邮箱 1.2.3登录你的邮箱下载(你的噶) 2.安装 2.1双击安装 2.2选择安…

分块矩阵的转置

证明 则 证明:令,有,对它做一个分块使得和后面的分块矩阵中的是同型矩阵,要证明(任意的),需要证明1)是一个的矩阵 2)任意的 首先证明1)我们先定义两个函…

HarmonyOS ArkUI工程框架解析

通过 HarmonyOS Developer 官网我们可以了解 ArkUI 是一套声明式开放框架,开发者可以基于 ArkTS 语法设计一套极简的 DSL 以及丰富的 UI 组件完成跨设备的界面开发。 那么 ArkUI 是如何实现这一套声明式开放框架的呢?本文将通过分析开源的 HarmonyOS 渲染…

记录devtmpfs:error mounting -2问题的解决

ext4文件系统制作有问题. 重新制作文件系统烧录 /dev文件夹丢失

软考攻略/超详细/系统集成项目管理工程师/基础知识分享04

第二章 信息技术发展 2.1信息技术及其发展 2.1.1 计算机软硬件(了解) 在许多情况下,计算机的某些功能既可以由硬件实现,也可以由软件来实现。 1、计算机硬件 计算机硬件主要分为:控制器、运算器、存储器、输入设备和…

开发中如何在运行/调试时将项目热部署到Tomcat

这里有一篇不错的博客,可以参考 http://t.csdnimg.cn/oWcgm 正常情况下,我们将web项目打包成war包后,需要放到tomcat的webapps路径下,然后启动tomcat,才能正常访问。但是这在开发阶段是极为不便的。因此可以使用两种方…

基于机器学习的工业制造缺陷分析预测系统

B站视频及代码下载:基于机器学习的工业制造缺陷分析预测系统-视频-代码 1. 项目简介 制造缺陷是工业生产过程中面临的重大挑战之一,对产品质量和生产效率产生直接影响。准确预测和分析制造缺陷的发生,可以帮助企业提高生产质量、降低成本&…

DNS 服务器的搭建(正向区域配置)

一、Windows DNS 正向区域配置 1.实验目标 2.拓扑结构 3.实验需求 4.配置要点 5.配置步骤 1.配置各主机 IP 地址及网关 2.DNS 服务器服务部署 3.验证实验 一、Windows DNS 正向区域配置 1.实验目标 掌握 DNS 的功能和基本操作 熟悉公网 DNS 架构 掌握 DNS …

豆瓣同城活动采集

可采集豆瓣同城活动,来辅助分析一个城市的文商旅体活跃繁荣程度。 示例数据: 活动网址:已屏蔽不显示 封图网址:已屏蔽不显示 标题:【百年老号-本地观众力捧】谦祥益相声茶馆-陆家嘴店 开始日期:2024-0…

tomcat在idea中 乱码(service ,catalina log)

我试了很多方法,把idea中的所有配置都改成了utf-8,(包括修改vm配置,fileEndcoding,外部文件endcodeing ...等等)都没有改好, 最后在修改了tomcat的配置文件,就好了 在tomcat的安装…

【C++ 第十六章】哈希

1. unordered系列关联式容器 在C98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到 ,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好 的查询是,进行…

Modern C++——函数参数类型的分类和使用

大纲 基本定义值类型左值引用非常量左值引用常量左值引用 右值引用总结 在C中,函数参数主要有两种方式:值类型和引用类型。其中引用类型又分为:左值引用和C11引入的右值引用。下面我们分别对其进行介绍。 基本定义 要弄清楚这些概念&#x…

三级_网络技术_51_应用题

一、 请根据下图所示网络结构回答下列问题。 1.填写路由器RG的路由表项。 目的网络/掩码长度输出端口__________S0(直接连接)__________S1(直接连接)__________S0__________S1__________S0__________S1 2.如果需要监听路由器RE…

mysql理论学习上

1:常⻅的SQL语句 1.1sql介绍 SQL 是⽤于访问和处理数据库的标准的计算机语⾔。 SQL,指结构化查询语⾔,全称是 Structured Query Language。SQL 让您可以访问和处理数据库。 SQL 是⼀种 ANSI(American National Standards Inst…

SSRF漏洞(二)

本文仅作为学习参考使用,本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言: 本文主要讲解依靠phpstudy搭建pikachu靶场。 phpstudy下载使用以及搭建本地SQL labs靶场 SSRF漏洞(一) 一,靶场搭建。 靶场…

用Python实现时间序列模型实战——Day1:时间序列的基本概念

一、学习内容 1. 时间序列数据的定义与特点 定义: 时间序列数据是一组按时间顺序排列的观测值。时间序列的每个观测值都与特定时间点相关联。例如,气温每天的记录、股票每日的收盘价等。 特点: 时间依赖性:时间序列数据的一个…

ssm基于微信小程序的食堂窗口自助点餐系统源码调试讲解

1. 环境搭建 JDK 1.8:确保您的系统已安装JDK 1.8,并配置好环境变量。JDK 1.8 是目前很多Java项目仍在使用的稳定版本,适用于SSM框架。Tomcat 7:安装并配置Tomcat 7作为您的Web服务器。Tomcat 7 支持Servlet 3.0和JSP 2.2&#xf…