嵌入式驱动开发详解8(阻塞/非阻塞/异步通信)

news2025/1/7 5:31:20

文章目录

  • 前言
  • 阻塞
  • 非阻塞
  • 异步通知
  • 后续

前言

首先来回顾一下“中断”,中断是处理器提供的一种异步机制,我们配置好中断以后就 可以让处理器去处理其他的事情了,当中断发生以后会触发我们事先设置好的中断服务函数, 在中断服务函数中做具体的处理。同样的,Linux 应用程序可以通过阻塞或者非阻塞这两种方式来访问驱动设备,通过阻塞方式访问的话应用程序会处于休眠态,等待驱动设备可以使用,非阻塞方式的话会通过 poll 函数来不断的轮询,查看驱动设备文件是否可以使用。这两种方式都需要应用程序主动的去查询设备的使用情况;“信号”为此应运而生,信号类似于我们硬件上使用的“中断”,只不过信号是软件层次上的。算是在软件层次上对中断的一种模拟,驱动可以通过主动向应用程序发送信号的方式来报告自己可以访问了,应用程序获取到信号以后就可以从驱动设备中读取或者写入数据了,这就是异步通行,接下来我将逐一分析阻塞,非阻塞和异步通知三种访问模式。

阻塞

在这里插入图片描述原理:应用程序调用 read 函数从设备中读取数据,当设备不可用或数据未准备好的 时候就会进入到休眠态。等设备可用的时候就会从休眠态唤醒,然后从设备中读取数据返回给 应用程序。
特点:当设备文件不可操作的时候进程可以进入休眠态,这样可以将 CPU 资源让出来。
使用方法Linux 内核提供了等待队列(wait queue)来实现阻塞进程的唤醒工作,先创建并初始化一个等待队列------>每个访问设备的进程都是一个队列项,当设备不可用的时候就要将这些进程对应的等待队列项添加到等待队列里面,添加到等待队列头中以后进程才能进入休眠态------>当设备可以使用的时候就要唤醒进入休眠态的进程,一般在中断函数里面完成唤醒工作。
API函数:API详细介绍肯定没有百度自行搜索详细,这里只列举一些API函数。

  1. 等待队列头初始化:
    void init_waitqueue_head(wait_queue_head_t *q)
  2. 定义并初始化一个等待队列项:
    DECLARE_WAITQUEUE(name, tsk)
  3. 将队列项添加/移除等待队列头:
    void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
    void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
  4. 等待唤醒(手动唤醒):
    void wake_up(wait_queue_head_t *q)
    void wake_up_interruptible(wait_queue_head_t *q)
  5. 等待唤醒(事件唤醒):
    在这里插入图片描述

非阻塞

在这里插入图片描述原理:应用程序使用非阻塞访问方式从设备读取数据,当设备不可用或 数据未准备好的时候会立即向内核返回一个错误码,表示数据读取失败。应用程序会再次重新读取数据,这样一直往复循环,直到数据读取成功。
特点:需要应用程序通过 poll 函数不断的轮询。
使用方法:应用程序通过 select、epoll 或 poll 函数来查询设备是否可以操作,如果可以操作的话就从设备读取或者向设备写入数据。当应用程序调用 select、epoll 或 poll 函数的时候设备驱动程序中的 poll 函数就会执行,因此需要在设备驱动程序中编写 poll 函数。
API函数

  • select函数:在单个线程中,select 函数能够监视的文件描述符数量有最大的限制,一般为 1024。
    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
  • poll函数:poll 函数本质上和 select 没有太大的差别,但是 poll 函数没有最大文件描述符限制。
    int poll(struct pollfd *fds, nfds_t nfds, int timeout)
  • epoll函数:epoll 就是为处理大并发而准备的,一般常常在网络编程中使用 epoll 函数。
    int epoll_create(int size)//size从 Linux2.6.8 开始此参数已经没有意义了,随便填写一个大于 0 的值就可以。
    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
    int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
  • 驱动程序 poll 函数:当应用程序调用 select 或 poll 函数来对驱动程序进行非阻塞访问的时候,驱动程序 file_operations 操作集中的 poll 函数就会执行。
    unsigned int (*poll) (struct file *filp, struct poll_table_struct *wait)
    驱动程序的 poll 函数中调用 poll_wait 函数,poll_wait 函数不会引起阻塞,只是 将应用程序添加到 poll_table 中
    void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)

异步通知

原理:异步通知的核心就是信号,在 arch/xtensa/include/uapi/asm/signal.h 文件中定义了 Linux 所支 持的所有信号:在这里插入图片描述“kill -9 PID”杀死指定进程的方法就是向指定的进程(PID)发送 SIGKILL 这个信号。当按下键盘上的 CTRL+C 组合键以后会向当前正在占用终端的应用程序发 出 SIGINT 信号,SIGINT 信号默认的动作是关闭当前应用程序。
特点:驱动通过主动向应用程序发送信号来报告自己可以访问,而不是通过应用程序来访问自己。
使用方法:如果要使用异步通知,需要在设备驱动中实现 file_operations 操作集中的 fasync 函数,fasync 函数里面一般通过调用 fasync_helper 函数来初始化前面定义的 fasync_struct 结构体指针,当应用程序通过“fcntl(fd, F_SETFL, flags | FASYNC)”改变 fasync 标记的时候,驱动程序 file_operations 操作集中的 fasync 函数就会执行。当设备可以访问的时候,驱动程序需要向应用程序发出信号,相当于产生“中断”。kill_fasync 函数负责发送指定的信号,应用程序收到信号后就会执行对应的中断回调函数;在关闭驱动文件的时候需要在 file_operations 操作集中的 release 函数中释放 fasync_struct。

后续

三种访问方式都有对应的例程,可以参考链接:https://github.com/NUAATRY/imx6ull_dev 中的实验12-14。

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

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

相关文章

人工智能之数学基础:向量内积以及应用

本文重点 向量的点积(Dot Product),又称数量积(Scalar Product)或内积,是线性代数中的一个重要概念。它接受两个向量作为输入,并返回一个实数作为输出。点积不仅在数学和物理学中有广泛应用,而且在人工智能领域也扮演着重要角色。 内积 在数学上,向量x和向量y的内积…

集线器,交换机,路由器,mac地址和ip地址知识记录总结

一篇很不错的视频简介 基本功能 从使用方面来说,都是为了网络传输的标识,和机器确定访问对象 集线器、交换机和路由器 常听到路由器和集线器,下面是区别: 集线器 集线器:一个简单的物理扩展接口数量的物理硬件。…

linux 逻辑卷挂盘

1.输入 sudo-i 转到root账号下。 2. 输入root密码后登录,输入parted -l ,发现与以前的挂盘不一样,未挂的盘与系统盘在一起,都是/dev/vda里。 2.输入 lsblkr,查看逻辑分区的设备名称 3. 新增目录 mkdir /data 4. 尝试直接将逻辑分…

python23-常用的第三方库01:request模块-爬虫

requests 模块是 Python 中的一个第三方库,用于发送 HTTP 请求。 它提供了一个简单且直观的 API,使得发送网络请求和解析响应变得非常容易。requests 模块支持各种 HTTP 方法,如 GET、POST、PUT、DELETE 等,并且具有处理 cookies…

解释一下:运放的输入失调电流

输入失调电流 首先看基础部分:这就是同相比例放大器 按照理论计算,输入VIN=0时,输出VOUT应为0,对吧 仿真与理论差距较大,有200多毫伏的偏差,这就是输入偏置电流IBIAS引起的,接着看它的定义 同向和反向输入电流的平均值,也就是Ib1、Ib2求平均,即(Ib1+Ib2)/2 按照下面…

常规继承类对象大小

这个相对简单&#xff0c;只需要考虑类对象大小的累加和内存对齐 #include<iostream> using namespace std;class Base { public:int ma;int mb;char mc; };class Derive :public Base { public:int md; };class Derive2 :public Derive { public:int me; };int main() …

Scrum中敏捷项目经理(Scrum Master)扮演什么角色?

敏捷开发模式已经逐渐被主流的软件研发团队所接受&#xff0c;其中Scrum是最具代表性的敏捷方法之一。Scrum框架中有三个核心角色&#xff1a;Product Owner&#xff08;PO&#xff09;、Scrum Master&#xff08;SM&#xff09;和Development Team&#xff08;DT&#xff09;。…

[网络安全]数据安全领域关键技术总结

去标识计算技术 概念 去标识计算 (Differential Privacy) 是一种数据隐私保护技术&#xff0c;它可以在不暴露个人敏感信息的前提下进行统计分析&#xff0c;并保证对隐私的泄露控制在可承受的范围之内。 底层逻辑 基于差分隐私的去标识计算是指在计算处理中采用一些差分隐私…

手机租赁平台开发实用指南与市场趋势分析

内容概要 在当今快速变化的科技时代&#xff0c;手机租赁平台的发展如火如荼。随着越来越多的人希望使用最新款的智能手机&#xff0c;但又不愿意承担昂贵的购机成本&#xff0c;手机租赁平台应运而生。这种模式不仅为用户提供了灵活的选择&#xff0c;还为企业创造了新的商机…

【从零开始入门unity游戏开发之——C#篇42】C#补充知识——随机数(Random)、多种方法实现string字符串拼接、语句的简写

文章目录 一、随机数1、Random.Next()生成随机整数示例&#xff1a;生成一个随机整数生成指定范围内的随机整数 2、Random.NextSingle生成随机浮点数示例&#xff1a;生成随机浮点数 3、 生成随机字母或字符示例&#xff1a;生成随机字母示例&#xff1a;生成随机小写字母 二、…

overleaf写学术论文常用语法+注意事项+审阅修订

常用语法 导入常用的宏包 \usepackage{cite} \usepackage{amsmath,amssymb,amsfonts} \usepackage{algorithmic} \usepackage{algorithm} \usepackage{graphicx} \usepackage{subfigure} \usepackage{textcomp} \usepackage{xcolor} \usepackage{lettrine} \usepackage{booktab…

Rabbitmq追问1

如果消费端代码异常&#xff0c;未手动确认&#xff0c;那么这个消息去哪里 2024-12-31 21:19:12 如果消费端代码发生异常&#xff0c;未手动确认&#xff08;ACK&#xff09;的情况下&#xff0c;消息的处理行为取决于消息队列的实现和配置&#xff0c;以下是基于 RabbitMQ …

DeepSpeed训练得到checkpoint如何像Huggingface模型一样评测evaluation?zero_to_fp32.py有什么用?怎么用?

DeepSpeed训练得到checkpoint如何像Huggingface模型一样评测evaluation&#xff1f; 具体步骤 首先看一个样例&#xff1a; 这是我用open-instruct框架&#xff0c;使用DeepSpeed训练1728个steps得到的一个checkpoint。请注意&#xff0c;下文我演示用的例子是基于step_1152&…

游戏如何检测Root权限

Root权限&#xff0c;即超级用户权限&#xff0c;在Android系统中&#xff0c;获取Root权限意味着用户可以修改系统文件、移除预装应用、安装特殊应用等。 在Root环境下&#xff0c;游戏面临着相当大的安全隐患&#xff0c;用户获取了最高权限&#xff0c;意味着可以通过各类工…

【UE5 C++课程系列笔记】21——弱指针的简单使用

目录 概念 声明和初始化 转换为共享指针 打破循环引用 弱指针使用警告 概念 在UE C 中&#xff0c;弱指针&#xff08;TWeakPtr &#xff09;也是一种智能指针类型&#xff0c;主要用于解决循环引用问题以及在不需要强引用保证对象始终有效的场景下&#xff0c;提供一种可…

微信小程序中的 storage(本地存储)和内存是两个完全不同的存储区域

这是一个非常关键且容易混淆的概念 既然 this.globalData.appId appId 是将 appId 存储在内存中&#xff0c;为什么微信小程序中的 wx.getStorage 和 wx.setStorage&#xff08;本地存储&#xff09;中没有 appId&#xff0c;并且您提出了一个非常重要的疑问&#xff1a;stor…

DevSecOps自动化在安全关键型软件开发中的实践、Helix QAC Klocwork等SAST工具应用

DevSecOps自动化对于安全关键型软件开发至关重要。 那么&#xff0c;什么是DevSecOps自动化&#xff1f;具有哪些优势&#xff1f;为何助力安全关键型软件开发&#xff1f;让我们一起来深入了解~ 什么是DevSecOps自动化&#xff1f; DevSecOps自动化是指在软件开发生命周期的各…

回归预测 | MATLAB实现CNN-GRU卷积门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现CNN-GRU卷积门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-GRU卷积门控循环单元多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现CNN-GRU卷积门控循环单元多输入单输出回归预测 数据准备&#x…

小程序学习06——uniapp组件常规引入和easycom引入语法

目录 一 组件注册 1.1 组件全局注册 1.2 组件全局引入 1.3 组件局部引入 页面引入组件方式 1.3.1 传统vue规范&#xff1a; 1.3.2 通过uni-app的easycom 二 组件的类型 2.1 基础组件列表 一 组件注册 1.1 组件全局注册 &#xff08;a&#xff09;新建compoents文件…

股市学习 seekingalpha tradingview

EMA EMA&#xff08;Exponential Moving Average&#xff09;是一种技术分析中常用的指标&#xff0c;用于平滑股价或其他资产价格的波动&#xff0c;以帮助分析价格走势的趋势和方向。EMA与简单移动平均&#xff08;SMA&#xff09;类似&#xff0c;但对最新价格的权重更大&a…