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

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石②

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石②

  • 第十九章 驱动程序基石②
    • 19.3 异步通知
      • 19.3.1 适用场景
      • 19.3.2 使用流程
      • 19.3.3 驱动编程
      • 19.3.4 应用编程
      • 19.3.5 现场编程
      • 19.3.6 上机编程
      • 19.3.7 异步通知机制内核代码详解
    • 19.4 阻塞与非阻塞
      • 19.4.1 应用编程
      • 19.4.2 驱动编程
      • 19.4.3 驱动开发原则

第十九章 驱动程序基石②

在这里插入图片描述

19.3 异步通知

使用 GIT命令载后,本节源码位于这个目录下:

01_all_series_quickstart\ 
05_嵌入式 Linux驱动开发基础知识\source\ 
06_gpio_irq\ 05_read_key_irq_poll_fasync 

19.3.1 适用场景

在前面引入中断时,我们曾经举过一个例子:
在这里插入图片描述

妈妈怎么知道卧室里小孩醒了?
① 时不时进房间看一下:查询方式
简单,但是累
② 进去房间陪小孩一起睡觉,小孩醒了会吵醒她:休眠-唤醒
不累,但是妈妈干不了活了
③ 妈妈要干很多活,但是可以陪小孩睡一会,定个闹钟:poll方式 要浪费点时间,但是可以继续干活。
妈妈要么是被小孩吵醒,要么是被闹钟吵醒。
④ 妈妈在客厅干活,小孩醒了他会自己走出房门告诉妈妈:异步通知 妈妈、小孩互不耽误
使用休眠-唤醒、POLL机制时,都需要休眠等待某个事件发生时,它们的差别在于后者可以指定休眠的时长。
在现实生活中:妈妈可以不陪小孩睡觉,小孩醒了之后可以主动通知妈妈。
如果 APP不想休眠怎么办?也有类似的方法:驱动程序有数据时主动通知APP,APP收到信号后执行信息处理函数。
什么叫“异步通知”?
你去买奶茶:
你在旁边等着,眼睛盯着店员,生怕别人插队,他一做好你就知道:你是主动等待他做好,这叫“同步”。 你付钱后就去玩手机了,店员做好后他会打电话告诉你:你是被动获得结果,这叫“异步”。

19.3.2 使用流程

驱动程序怎么通知 APP:发信号,这只有 3个字,却可以引发很多问题:
① 谁发:驱动程序发
② 发什么:信号
③ 发什么信号:SIGIO
④ 怎么发:内核里提供有函数
⑤ 发给谁:APP,APP要把自己告诉驱动
⑥ APP收到后做什么:执行信号处理函数
⑦ 信号处理函数和信号,之间怎么挂钩:APP注册信号处理函数
小孩通知妈妈的事情有很多:饿了、渴了、想找人玩。
Linux系统中也有很多信号,在 Linux内核源文件 include\uapi\asm-generic\signal.h中,有很多信号的宏定义:
在这里插入图片描述

就 APP而言,你想处理 SIGIO信息,那么需要提供信号处理函数,并且要跟 SIGIO挂钩。这可以通过一个 signal函数来“给某个信号注册处理函数”,用法如下:
在这里插入图片描述

APP还要做什么事?想想这几个问题:
① 内核里有那么多驱动,你想让哪一个驱动给你发 SIGIO信号?
APP要打开驱动程序的设备节点。
② 驱动程序怎么知道要发信号给你而不是别人?
APP要把自己的进程 ID告诉驱动程序。
③ APP有时候想收到信号,有时候又不想收到信号:
应该可以把 APP的意愿告诉驱动。
驱动程序要做什么?发信号。
① APP设置进程 ID时,驱动程序要记录下进程 ID;
② APP还要使能驱动程序的异步通知功能,驱动中有对应的函数:
APP打开驱动程序时,内核会创建对应的 file结构体,file中有 f_flags; f_flags中有一个 FASYNC位,它被设置为 1时表示使能异步通知功能。
当 f_flags中的 FASYNC位发生变化时,驱动程序的 fasync函数被调用。
③ 发生中断时,有数据时,驱动程序调用内核辅助函数发信号。
这个辅助函数名为 kill_fasync。
完美!
APP收到信号后,是怎么执行信号处理函数的?
这个,很难,有兴趣的话就看本节最后的文档。初学者没必要看。
综上所述,使用异步通知,也就是使用信号的流程如下图所示:
在这里插入图片描述

重点从②开始:
② APP给 SIGIO这个信号注册信号处理函数 func,以后 APP收到 SIGIO信号时,这个函数会被自动调用;
③ 把 APP的 PID(进程 ID)告诉驱动程序,这个调用不涉及驱动程序,在内核的文件系统层次记录 PID; ④ 读取驱动程序文件 Flag;
⑤ 设置 Flag里面的 FASYNC位为 1:当 FASYNC位发生变化时,会导致驱动程序的 fasync被调用;
⑥⑦ 调用 faync_helper,它会根据 FAYSNC的值决定是否设置 button_async->fa_file=驱动文件filp:
驱动文件 filp结构体里面含有之前设置的 PID。
⑧ APP可以做其他事;
⑨⑩ 按下按键,发生中断,驱动程序的中断服务程序被调用,里面调用 kill_fasync发信号;
⑪⑫⑬ APP收到信号后,它的信号处理函数被自动调用,可以在里面调用 read函数读取按键。

19.3.3 驱动编程

使用异步通知时,驱动程序的核心有 2:

① 提供对应的 drv_fasync函数; ② 并在合适的时机发信号。
drv_fasync函数很简单,调用 fasync_helper函数就可以,如下:

static struct fasync_struct *button_async; 
static int drv_fasync (int fd, struct file *filp, int on) 
{ return fasync_helper (fd, filp, on, &button_async); 
} 

fasync_helper函数会分配、构造一个 fasync_struct结构体 button_async:
① 驱动文件的 flag被设置为 FAYNC时:

button_async->fa_file = filp;  // filp表示驱动程序文件,里面含有之前设置的 PID ② 驱动文件被设置为非 FASYNC时: 
button_async->fa_file = NULL; 

以后想发送信号时,使用 button_async作为参数就可以,它里面“可能”含有 PID。
什么时候发信号呢?在本例中,在 GPIO中断服务程序中发信号。
怎么发信号呢?代码如下:

kill_fasync (&button_async, SIGIO, POLL_IN); 

第 1个参数:button_async->fa_file非空时,可以从中得到 PID,表示发给哪一个 APP; 第 2个参数表示发什么信号:SIGIO;
第 3个参数表示为什么发信号:POLL_IN,有数据可以读了。(APP用不到这个参数)

19.3.4 应用编程

应用程序要做的事情有这几件:
① 编写信号处理函数:

static void sig_func(int sig) 
{ int val; read(fd, &val, 4); printf("get button : 0x%x\n", val); } 

② 注册信号处理函数:

signal(SIGIO, sig_func); 

③ 打开驱动:

fd = open(argv[1], O_RDWR); 

④ 把进程 ID告诉驱动:

fcntl(fd, F_SETOWN, getpid()); 

⑤ 使能驱动的 FASYNC功能:

flags = fcntl(fd, F_GETFL); 
fcntl(fd, F_SETFL, flags | FASYNC); 

19.3.5 现场编程

19.3.6 上机编程

19.3.7 异步通知机制内核代码详解

还没写

19.4 阻塞与非阻塞

所谓阻塞,就是等待某件事情发生。比如调用 read读取按键时,如果没有按键数据则 read函数不会返回,它会让线程休眠等待。
使用 poll时,如果传入的超时时间不为 0,这种访问方法也是阻塞的。

使用 poll时,可以设置超时时间为 0,这样即使没有数据它也会立刻返回,这就是非阻塞方式。能不能让 read函数既能工作于阻塞方式,也可以工作于非阻塞方式?可以!
APP调用 open函数时,传入 O_NONBLOCK,就表示要使用非阻塞方式;默认是阻塞方式。
注意:对于普通文件、块设备文件,O_NONBLOCK不起作用。
注意:对于字符设备文件,O_NONBLOCK起作用的前提是驱动程序针对 O_NONBLOCK做了处理。
只能在 open时表明 O_NONBLOCK吗?在 open之后,也可以通过 fcntl修改为阻塞或非阻塞。
使用 GIT命令载后,本节源码位于这个目录下:

01_all_series_quickstart\ 
05_嵌入式 Linux驱动开发基础知识\source\ 
06_gpio_irq\ 06_read_key_irq_poll_fasync_block 

19.4.1 应用编程

open时设置:

int  fd = open(/dev/xxx”, O_RDWR | O_NONBLOCK);  /* 非阻塞方式 */ int  fd = open(/dev/xxx”, O_RDWR );  /* 阻塞方式 */ 

open之后设置:

int flags = fcntl(fd, F_GETFL); 
fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* 非阻塞方式 */ 
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);  /* 阻塞方式 */ 

19.4.2 驱动编程

以 drv_read为例:

static ssize_t drv_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK) return -EAGAIN; wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue)); …… 
} 

从驱动代码也可以看出来,当 APP打开某个驱动时,在内核中会有一个 struct file结构体对应这个驱动,这个结构体中有 f_flags,就是打开文件时的标记位;可以设置 f_flasgs的 O_NONBLOCK位,表示非阻塞;也可以清除这个位表示阻塞。
驱动程序要根据这个标记位决定事件未就绪时是休眠和还是立刻返回。

19.4.3 驱动开发原则

驱动程序程序“只提供功能,不提供策略”。就是说驱动程序可以提供休眠唤醒、查询等等各种方式,,驱动程序只提供这些能力,怎么用由 APP决定。

相关文章:

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石②

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石② 第十九章 驱动程序基石②19.3 异步通知19.3.1 适用场景19.3.2 使用流程19.3.3 驱动编程19.3.4 应用编程19.3.5 现场编程19.3.6 上机编程19.3.7 异步通知机制内核代码详解 19.4 阻塞与非阻塞19.4.1 应用编程19.4.2 驱动编程…...

trycatch、throw、throws

在Java中,try-catch、throw和throws是用于处理异常的重要关键字和机制,它们的作用如下: try-catch:try-catch 是用于捕获和处理异常的语句块。在try块中放置可能引发异常的代码。如果在try块中的代码引发了异常,控制流会跳转到与异常类型匹配的catch块。在catch块中,可以…...

问 ChatGPT 关于 GPT 的事情:数据准备篇

一、假如你是一名人工智能工程师,手里有一个65B的GPT大模型,但你需要一个6B左右的小模型,你会怎么做? 答:作为人工智能工程师,如果我手里有一个65B的GPT大模型,而我需要一个6B左右的小模型&…...

leetcode_17电话号码的组合

1. 题意 输出电话号码对应的字母左右组合 电话号码的组合 2. 题解 回溯 class Solution { public:void gen_res(vector<string> &res, vector<string> &s_m,string &digits, string &t, size_t depth) {if (depth digits.size()) {if ( !t.em…...

记录使用vue-test-utils + jest 在uniapp中进行单元测试

目录 前情安装依赖package.json配置jest配置测试文件目录编写setup.js编写第一个测试文件jest.fn()和jest.spyOn()jest 解析scss失败测试vuex$refs定时器测试函数调用n次手动调用生命周期处理其他模块导入的函数测试插槽 前情 uniapp推荐了测试方案dcloudio/uni-automator&…...

《C和指针》笔记30:函数声明数组参数、数组初始化方式和字符数组的初始化

文章目录 1. 函数声明数组参数2. 数组初始化方式2.1 静态初始化2.2 自动变量初始化 2.2 字符数组的初始化 1. 函数声明数组参数 下面两个函数原型是一样的&#xff1a; int strlen( char *string ); int strlen( char string[] );可以使用任何一种声明&#xff0c;但哪个“更…...

VBA技术资料MF64:遍历单元格搜索字符并高亮显示

【分享成果&#xff0c;随喜正能量】不要在乎他人的评论&#xff0c;不必理论与他人有关的是非&#xff0c;你只要做好自己就够了。苔花如米小&#xff0c;也学牡丹开。无论什么时候&#xff0c;都要有忠于自己的勇气&#xff0c;去做喜欢的事&#xff0c;去认识喜欢的人&#…...

一键智能视频编辑与视频修复算法——ProPainter源码解析与部署

前言 视频编辑和修复确实是随着电子产品的普及变得越来越重要的技能。有许多视频编辑工具可以帮助人们轻松完成这些任务如&#xff1a;Adobe Premiere Pro&#xff0c;Final Cut Pro X&#xff0c;Davinci Resolve&#xff0c;HitFilm Express&#xff0c;它们都提供一些视频修…...

Flutter开发环境的配置

2023-10最新版本 flutter SDK版本下载地址 https://flutter.cn/docs/development/tools/sdk/releases gradle各版本快速下载地址 https://blog.csdn.net/ii950606/article/details/109105402 JAVA SDK下载地址 https://www.oracle.com/java/technologies/downloads/#java…...

【超详细】Wireshark教程----Wireshark 分析ICMP报文数据试验

一&#xff0c;试验环境搭建 1-1 试验环境示例图 1-2 环境准备 两台kali主机&#xff08;虚拟机&#xff09; kali2022 192.168.220.129/24 kali2022 192.168.220.3/27 1-2-1 网关配置&#xff1a; 编辑-------- 虚拟网路编辑器 更改设置进来以后 &#xff0c;先选择N…...

Linux命令(92)之rm

linux命令之rm 1.rm介绍 linux命令rm是用来删除一个或多个文件/目录&#xff0c;由于其删除的不可逆性&#xff0c;建议在日常工作中一定要慎用 2.rm用法 rm [参数] 文件/目录 rm常用参数 参数说明-r递归删除文件或目录-f不提示强制删除-i删除文件或目录前进行确认-v详细显…...

Mysql主从复制数据架构全面解读

大家好&#xff0c;我是山子&#xff0c;今天给大家分析Mysql 实现主从复制的方方面面&#xff0c;主从复制当然也是我们做读写分离的前提&#xff0c;以下内容是从各网络平台摘录整理总结归纳在一起的&#xff1b;内容已经从主从复制的各方面的维度进行了阐述&#xff1b;非常…...

ios证书类型及其作用说明

ios证书类型及其作用说明 很多刚开始接触iOS证书的开发者可能不是很了解iOS证书的类型功能和概念。下面对iOS证书的几个方面进行介绍。 apple开发账号分类&#xff1a; 免费账号&#xff1a; 无需支付费用给apple&#xff0c;使用个人信息注册的账号 可以开发测试安装&…...

警告-Ubuntu提示W: Possible missing firmware xxx解决方法

目录 现象原因解决方法 现象 当执行 sudo apt-get update或者sudo apt-get dist-upgrade时&#xff0c;有如下警告&#xff1a; W: Possible missing firmware /lib/firmware/rtl_nic/rtl8125a-3.fw for module r8169 W: Possible missing firmware /lib/firmware/rtl_nic/rt…...

有时候,使用 clang -g test.c 编译出可执行文件后,发现 gdb a.out 进行调试无法读取符号信息,为什么?

经过测试&#xff0c;gdb 并不是和所有版本的 llvm/clang 都兼容的 当 gdb 版本为 9.2 时&#xff0c;能支持 9.0.1-12 版本的 clang&#xff0c;但无法支持 16.0.6 版本的 clang 可以尝试使用 LLVM 专用的调试器 lldb 我尝试使用了 16.0.6 版本的 lldb 调试 16.0.6 的 clan…...

UG\NX二次开发 信息窗口的一些操作 NXOpen/ListingWindow

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 信息窗口的一些操作 NXOpen/ListingWindow 效果: 代码: #include "me.hpp" #include <NXOpen/ListingWindow.hxx> #include <…...

macbook电脑磁盘满了怎么删东西?

macbook是苹果公司的一款高性能笔记本电脑&#xff0c;受到很多用户的喜爱。但是&#xff0c;如果macbook的磁盘空间不足&#xff0c;可能会导致一些问题&#xff0c;比如无法开机、运行缓慢、应用崩溃等。那么&#xff0c;macbook磁盘满了无法开机怎么办&#xff0c;macbook磁…...

解释 RESTful API,以及如何使用它构建 web 应用程序

RESTful API是一种基于HTTP协议&#xff0c;使用REST架构风格设计的API。其核心思想是将所有的Web应用程序资源抽象为一组资源集合&#xff0c;并通过HTTP协议中的GET、POST、PUT、DELETE等几个方法对这些资源进行操作&#xff0c;使得Web应用程序能够方便地、高效地进行管理和…...

qml使用c++自定义listmodel数据

qml要使用c中自定义的model&#xff0c;首先该model类需要继承QAbstractListModel类&#xff0c;然后需要重写其中的三个函数&#xff0c;分别是 int rowCount(const QModelIndex &parent); QVariant data(const QModelIndex &index, int role Qt::DisplayRole); QHas…...

cf 解题报告 01

E. Power of Points Problem - 1857E - Codeforces 题意&#xff1a; 给你 n n n 个点&#xff0c;其整数坐标为 x 1 , … x n x_1,\dots x_n x1​,…xn​&#xff0c;它们位于一条数线上。 对于某个整数 s s s&#xff0c;我们构建线段[ s , x 1 s,x_1 s,x1​], [ s , x…...

傅里叶系列 P1 的定价选项

如果您想了解更多信息&#xff0c;请查看第 2 部分和第 3 部分。 一、说明 这是第一篇文章&#xff0c;我将帮助您获得如何使用这个新的强大工具来解决金融中的半分析问题并取代您的蒙特卡洛方法的直觉。 我们都知道并喜欢蒙特卡洛数字积分方法&#xff0c;但是如果我告诉你你可…...

第二十届北京消防展即将开启,汉威科技即将精彩亮相

10月10日~13日&#xff0c;第二十届中国国际消防设备技术交流展览会&#xff0c;将在北京市顺义区中国国际展览中心新馆隆重举行。该展会由中国消防协会举办&#xff0c;是世界三大消防品牌展会之一&#xff0c;本届主题为“助力产业发展&#xff0c;服务消防救援”。届时将有4…...

mongodb、mysql、redis 区别

MongoDB、MySQL 和 Redis 是三种不同的数据库管理系统,它们在数据存储、访问模型和使用场景方面有一些显著的区别。 1. 数据存储模型: MongoDB:MongoDB 是一种文档数据库,它使用 BSON(Binary JSON)格式来存储数据。数据以文档的形式组织,每个文档可以有不同的字段,文档…...

【Flutter】Flutter Web 开发 如何从 URL 中获取参数值

【Flutter】Flutter Web 开发 如何从 URL 中获取参数值 文章目录 一、前言二、Flutter Web 中的 URL 处理三、如何从 URL 中获取参数四、实际业务中的用法五、完整示例六、总结 一、前言 大家好&#xff01;我是小雨青年&#xff0c;今天我想和大家分享一下在 Flutter Web 开发…...

【Java 进阶篇】JDBC Statement:执行 SQL 语句的重要接口

在Java应用程序中&#xff0c;与数据库进行交互是一项常见的任务。为了执行数据库操作&#xff0c;我们需要使用JDBC&#xff08;Java Database Connectivity&#xff09;来建立与数据库的连接并执行SQL语句。Statement接口是JDBC中的一个重要接口&#xff0c;它用于执行SQL语句…...

Python与数据分析--Pandas操作进阶

目录 1.文件读取方式 1.1.绝对路径读取文件 1.2.相对路径读取文件 2.列表数据操作 2.1.列索引指定 2.2.代码数据对齐 3.创建新CSV文件 4.缺失值处理 4.1.缺失值创建 4.2.缺失值检索 4.3.缺失值查询 4.3.1.isnull()函数判断 4.3.2.notnull()函数判断 4.3.3.any()函数…...

国庆小练习

一、二、三 一、 创建一个双向链表&#xff0c; 将26个英文字母通过头插的方式插入到链表中 通过尾删的方式将数据读取出来并删除。main.c #include <my_head.h> #include "dblink.h"int main(int argc, const char *argv[]) {dblink *h create_head();for…...

springboot单体项目如何拆分成微服务

要将一个Spring Boot单体项目拆分成微服务&#xff0c;可以按照以下步骤进行操作&#xff1a; 识别业务域&#xff1a;首先&#xff0c;需要对单体项目进行业务域的划分。将项目中的功能按照业务领域进行分类&#xff0c;每个业务领域可以成为一个独立的微服务。 定义服务接口…...

解决recovery页面反转的问题

1.前言 在android 10.0的系统rom定制化开发工作中&#xff0c;在系统中recoverv的页面也是相关重要的一部分&#xff0c;在系统recovery ta升级等功能&#xff0c;都是需要recoverv功能的&#xff0c;在某些产品定制化中 在recovery的时候&#xff0c;发现居然旋转了180度&…...

如何使用nuScenes数据集格式的单帧数据推理(以DETR3D为例)

【请尊重原创&#xff01;转载和引用文章内容务必注明出处&#xff01;未经许可上传到某文库或其他收费阅读/下载网站赚钱的必追究责任&#xff01;】 无论是mmdetection3D还是OpenPCDet都只有使用数据集(使用哪个数据集由配置文件里指定)训练和测试的代码&#xff0c;没有使用…...

网站开发用什么字体一般/如何做seo优化

biti大师链接:http://biti_rainy.itpub.net/来自 “ ITPUB博客 ” &#xff0c;链接&#xff1a;http://blog.itpub.net/39335/viewspace-351665/&#xff0c;如需转载&#xff0c;请注明出处&#xff0c;否则将追究法律责任。 转载于:http://blog.itpub.net/39335/viewspace-…...

网站建设及/营销策划培训

总是想的很多&#xff0c;说的时候一句话都说不出来。 过去的就过去吧&#xff0c;新的开始&#xff0c;好好加油&#xff01; ps&#xff1a;这个博客不用了&#xff0c;退出集训队了。转载于:https://www.cnblogs.com/naix-x/p/3468413.html...

企业自助建站/长沙做网站的公司有哪些

弱菜的做法&#xff0c;生成所有子集&#xff0c;然后从集合元素个数少的开始判断。 有一个大坑是&#xff0c;所有的格子都是空地&#xff0c;这种情况下不用放&#xff0c;输出0。 1 #include <algorithm>2 #include <iostream>3 #include <cstring>4 #inc…...

个人怎么做网站排名优化/手机app免费下载

哈佛大学Harvard学校地址&#xff1a;51 Brattle St Camridge,MA 02138所在州&#xff1a;马萨诸塞州建校时间&#xff1a;1636学校网址&#xff1a;/2015年美国大学本科综合排名 第22015年美国大学最佳商学院排名 第12015年美国大学最佳医学院研究方向排名 第12015年美国大学管…...

机械厂做网站到底有没有效果/磁力搜索器 磁力猫在线

在设置中搜索python.linting.pylintPath如下 如果使用的是anaconda&#xff0c;在anaconda文件夹中寻找pylint应用程序的安装位置&#xff0c;例如&#xff1a;E:\anaconda\new\pkgs\pylint-2.2.2-py37_0\Scripts 如果没有安装anaconda&#xff0c;先检查是否安装了pylint&am…...

徐州网站建设推广/ip网站查询服务器

.Word 文档常德职业技术学院教案纸第 1 教案课 题Junit基础使用教学目标&#xff1a;含知识、能力和素质知识目标&#xff1a;1、掌握Junit基本使用&#xff1b;2、掌握Junit基本测试流程。能力目标&#xff1a;熟练使用Junit测试软件模块。态度目标&#xff1a;1、培养分析能…...