Linux学习第26天:异步通知驱动开发: 主动

news2024/11/28 8:43:14

Linux版本号4.1.15   芯片I.MX6ULL                                    大叔学Linux    品人间百味  思文短情长 


       在正式开启今天的学习前,讲一讲为什么标题中加入了【主动】俩字。之前学习的阻塞和非阻塞IO,都是在被动的接受应用程序的操作。而今天的学习的异步通知则是驱动程序自动的去上报自己的状态,类似于以前我们学习的中断机制。

        谈到【主动】,和大家共勉一句话:凡事先干起来,就能消除90%的焦虑。当我第一次看到这句话的时候,突然有种豁然开朗的感觉。往往大家都是在托腮忧虑自己想象中的困难而久久不知所措而停止行动。殊不知,我们自己想象中的大部分困难也只存在于我们的想象中。当着手开始行动时,你会发现,也许并不难。

        本篇笔记主要学习了嵌入式Linux异步通知驱动开发相关知识,主要内容包括异步通知的相关概念及驱动开发的过程。其中异步通知又包括异步通知简介、驱动中的信号处理以及应用程序对异步通知的处理。驱动开发包括设备树的修改、驱动开发及测试。其中驱动开发是本节重点需要关注的内容。

        本篇笔记的思维导图如下:

f2792c8a4df940519a8bdd74963786e1.png

一、异步通知

        关键字:主动 中断

1.异步通知简介

        关键字:信号

在应用程序中使用 signal 函数来设置指定信号的处理函数.

sighandler_t signal(int signum, sighandler_t handler)

signum:要设置处理函数的信号。
handler: 信号的处理函数。
返回值: 设置成功的话返回信号的前一个处理函数,设置失败的话返回 SIG_ERR。
 

2.驱动中的信号处理

1)、fasync_struct

struct fasync_struct {
spinlock_t fa_lock;
int magic;
int fa_fd;
struct fasync_struct *fa_next;
struct file *fa_file;
struct rcu_head fa_rcu;
};

        一般将 fasync_struct 结构体指针变量定义到设备结构体中。

2)、fasync函数

int (*fasync) (int fd, struct file *filp, int on)
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)

        当应用程序通过“fcntl(fd, F_SETFL, flags | FASYNC)”改变fasync 标记的时候,驱动程序 file_operations 操作集中的 fasync 函数就会执行。

        在关闭驱动文件的时候需要在 file_operations 操作集中的 release 函数中释放 fasync_struct,fasync_struct 的释放函数同样为 fasync_helper

3)、kill_fasync

        负责发送指定的信号。函数的原型如下:

void kill_fasync(struct fasync_struct **fp, int sig, int band)

fp:要操作的 fasync_struct。
sig: 要发送的信号。
band: 可读时设置为 POLL_IN,可写时设置为 POLL_OUT。


3.应用程序对异步通知的处理

1)、注册信号处理函数

2)、将本应用程序的进程号告诉给内核 

fcntl(fd, F_SETOWN, getpid())

3)、开启异步通知

flags = fcntl(fd, F_GETFL); /* 获取当前的进程状态 */
fcntl(fd, F_SETFL, flags | FASYNC); /* 开启当前进程异步通知功能 */

二、硬件原理图分析

9374cca617854814bce2c5c04ed16a3c.png

三、应用程序编写

1.修改设备树文件

2.程序编写

#include <linux/fcntl.h>//因为要用到相关的 API 函数。
struct fasync_struct *async_queue; /* 设备结构体中加入异步相关结构体 */
109 if(atomic_read(&dev->releasekey)) { /* 一次完整的按键过程 */
110 if(dev->async_queue)
111 kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
112 }

        如果是一次完整的按键过程,那么就通过 kill_fasync 函数发送 SIGIO 信号。

269 static int imx6uirq_fasync(int fd, struct file *filp, int on)
270 {
271 struct imx6uirq_dev *dev = (struct imx6uirq_dev *)
filp->private_data;
272 return fasync_helper(fd, filp, on, &dev->async_queue);
273 }

        imx6uirq_fasync 函数,为 file_operations 操作集中的 fasync 函数,此函数内容很简单,就是调用一下 fasync_helper。

281 static int imx6uirq_release(struct inode *inode, struct file *filp)
282 {
283 return imx6uirq_fasync(-1, filp, 0);
284 }

        release 函数,应用程序调用 close 函数关闭驱动设备文件的时候此函数就会执行,在此函数中释放掉 fasync_struct 指针变量。

292 .fasync = imx6uirq_fasync,
293 .release = imx6uirq_release,

        设置 file_operations 操作集中的 fasync release 这两个成员变量。

3.编写测试APP

27 /*
28 * SIGIO 信号处理函数
29 * @param - signum : 信号值
30 * @return : 无
31 */
32 static void sigio_signal_func(int signum)
33 {
34 int err = 0;
35 unsigned int keyvalue = 0;
36
37 err = read(fd, &keyvalue, sizeof(keyvalue));
38 if(err < 0) {
39 /* 读取错误 */
40 } else {
41 printf("sigio signal! key value=%d\r\n", keyvalue);
42 }
43 }

        sigio_signal_func 函数, SIGIO 信号的处理函数,当驱动程序有效按键按下以后就会发送 SIGIO 信号,此函数就会执行。此函数通过 read 函数读取按键值,然后通过printf 函数打印在终端上。

signal(SIGIO, sigio_signal_func);

        通过 signal 函数设置 SIGIO 信号的处理函数为 sigio_signal_func。

71 fcntl(fd, F_SETOWN, getpid()); /* 将当前进程的进程号告诉给内核 */
72 flags = fcntl(fd, F_GETFD); /* 获取当前的进程状态 */
73 fcntl(fd, F_SETFL, flags | FASYNC);/* 设置进程启用异步通知功能 */

        设置当前进程的状态,开启异步通知的功能。

四、运行测试

1.编译驱动程序和测试APP

1)、编译驱动程序

obj-m := asyncnoti.o

make -j32             asyncnoti.ko”的驱动模块
 

2)、编译测试APP

arm-linux-gnueabihf-gcc asyncnotiApp.c -o asyncnotiApp

应用程序asyncnotiApp

2.运行测试

depmod //第一次加载驱动的时候需要运行此命令
modprobe asyncnoti.ko //加载驱动
./asyncnotiApp /dev/asyncnoti

        按下开发板上的 KEY0 键,终端就会输出按键值。

五、总结

        本篇笔记主要学习了嵌入式Linux异步通知驱动开发相关知识,主要内容包括异步通知的相关概念及驱动开发的过程。


本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。

 

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

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

相关文章

MyBatis-Plus 实战教程四 idea插件

文章目录 插件功能分页插件配置分页插件分页API 通用分页实体实体开发接口改造PageQuery实体改造PageDTO实体 仓库地址 插件功能 MybatisPlus提供了很多的插件功能&#xff0c;进一步拓展其功能。目前已有的插件有&#xff1a; PaginationInnerInterceptor&#xff1a;自动分…

中微爱芯74逻辑兼容替代TI/ON/NXP工规品质型号全

这里写自定义目录标题 工业级型号全产品线概述![在这里插入图片描述](https://img-blog.csdnimg.cn/097ef810b2234f07b0c0c1e962a73761.png)批量应用行业头部客户兼容替代封装对照逻辑参数对比电平转换系列型号对照HC/HCT 系列型号对照AHC/AHCT 系列型号对照LV/LVC 系列型号对照…

【ARMv8 SIMD和浮点指令编程】NEON 通用数据处理指令——复制、反转、提取、转置...

NEON 通用数据处理指令包括以下指令(不限于): • DUP 将标量复制到向量的所有向量线。 • EXT 提取。 • REV16、REV32、REV64 反转向量中的元素。 • TBL、TBX 向量表查找。 • TRN 向量转置。 • UZP、ZIP 向量交叉存取和反向交叉存取。 1 DUP (element) 将…

无线电编码和记录和静音检测器 PlayOutONE LiveStream 5.0

直播编码器&#xff0c;随处流式传输。LiveStream 应用程序的多色图案屏幕截图&#xff0c;显示一波进入&#xff0c;四路流出来&#xff0c;LiveStream是一站式应用程序&#xff0c;可让您的电台在需要的地方输出。 对音频进行编码以进行流式传输&#xff0c;使用您最喜欢的V…

Megatron-LM GPT 源码分析(三) Pipeline Parallel分析

引言 本文接着上一篇【Megatron-LM GPT 源码分析&#xff08;二&#xff09; Sequence Parallel分析】&#xff0c;基于开源代码 GitHub - NVIDIA/Megatron-LM: Ongoing research training transformer models at scale &#xff0c;通过GPT的模型运行示例&#xff0c;从三个维…

【鸿蒙软件开发】ArkTS基础组件之TextClock(时间显示文本)、TextPicker(滑动选择文本)

文章目录 前言一、TextClock1.1 子组件1.2 接口参数TextClockController 1.3 属性1.4 事件1.5 示例代码 二、TextPicker2.1 子组件2.2 接口参数 2.3 属性2.4 事件2.5 示例代码 总结 前言 TextClock组件:通过文本将当前系统时间显示在设备上。支持不同时区的时间显示&#xff0…

MySQL实战2

文章目录 主要内容一.回访用户1.准备工作代码如下&#xff08;示例&#xff09;: 2.目标3.实现代码如下&#xff08;示例&#xff09;: 二.如何找到每个人每月消费的最大天数1.准备工作代码如下&#xff08;示例&#xff09;: 2.目标3.实现代码如下&#xff08;示例&#xff09…

Pandas时间序列、时间戳对象、类型转换、时间序列提取、筛选、重采样、窗口滑动

时间序列数据是指在时间间隔不变的情况下收集的时间点数据&#xff0c;可以用来分析事物的长期发展趋势&#xff0c;并对未来进行预测。 date_range()方法及参数 pandas.date_range(startNone, endNone, periodsNone, freqNone, tzNone, normalizeFalse, nameNone, inclusive‘…

08.K8S高可用方案

K8S高可用方案 1、高可用部署方式 官方提供两种高可用实现方式: 堆叠etcd 拓扑,其中 etcd 节点与控制平面节点共存;外部 etcd 节点,其中 etcd 与控制平面在不同的节点上运行;1.1、堆叠 etcd 拓扑 主要特点: 每个 master 节点上运行一个 apiserver 和 etcd, etcd 只与本…

Spring Security: 整体架构

Filter Spring Security 是基于 Sevlet Filter 实现的。下面是一次 Http 请求从 client 出发&#xff0c;与 Servlet 交互的图&#xff1a; 当客户端发送一个请求到应用&#xff0c;容器会创建一个 FilterChain&#xff0c;FilterChain 中包含多个 Filter 和 Servlet。这些 Fi…

C#,数值计算——分类与推理,基座向量机的 Svmgenkernel的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public abstract class Svmgenkernel { public int m { get; set; } public int kcalls { get; set; } public double[,] ker { get; set; } public double[] y { get; set…

构建第二大脑#知识库使用指南

fortelabs.com/blog/basboverview 《构建第二大脑&#xff1a;入门指南》提到一个步骤&#xff1a; 通过策划和管理您的个人信息流来减轻压力和“信息过载”创建一个内心平静的数字环境充分发挥您周围丰富学习资源的价值&#xff0c;例如在线课程、网络研讨会、书籍、文章、论坛…

threejs(8)-详解光线投射与物体交互

详解光线投射与物体交互 import * as THREE from "three"; // 导入轨道控制器 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; // 导入动画库 import gsap from "gsap"; // 导入dat.gui import * as dat from &qu…

QVHZO-A-06/18、QVHZE-A-06/36比例流量控制阀放大器

QVHZO-A-06/36、QVHZO-A-06/12、QVHZO-A-06/45、QVHZO-A-06/18、QVKZOR-A-10/65、QVKZOR-A-10/90、QVHZE-A-06/36、QVHZE-A-06/12、QVHZE-A-06/45、QVHZE-A-06/18、QVKZE-A-10/65、QVKZE-A-10/90带压力补偿的比例流量控制阀&#xff0c;直动式&#xff0c;不带位置传感器&#…

圆锥面积 题解

圆锥体积 描述 已知一个圆锥体的高 h 和底面积的半径 r &#xff0c;求该圆锥体的体积&#xff0c;保留3位小数。 圆锥底部圆面积S的计算公式为&#xfffd;&#xfffd;∗&#xfffd;∗&#xfffd;Sπ∗r∗r 这里的&#xfffd;3.14159π3.14159 圆锥体的体积V计算公式为…

可以提取图像文本的 5 大 Python 库

主要是了解并掌握文本定位和识别的OCR工具哦~ 光学字符识别是一个古老但依然具有挑战性的问题&#xff0c;涉及从非结构化数据中&#xff08;包括图像和PDF文档&#xff09;检测和识别文本。它在银行、电子商务和社交媒体内容管理等领域具有广泛的应用。 但与数据科学中的每个主…

FreeRTOS中osDelay和HAL_Delay的区别

问题场景 在FreeRTOS中创建了线程A、线程B&#xff0c;其中线程A优先级大于线程B。线程A、B任务代码如下: void A(void *argument) {while (1){printf("A\r\n");HAL_Delay(1000);} }void B(void *argument) {while (1){printf("B\r\n");HAL_Delay(1000);} …

基于springboot实现校园疫情防控系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现校园疫情防控系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&am…

回溯法(1)--装载问题和0-1背包

一、回溯法 回溯法采用DFS&#xff0b;剪枝的方式&#xff0c;通过剪枝删掉不满足条件的树&#xff0c;提高本身作为穷举搜索的效率。 回溯法一般有子集树和排列树两种方式&#xff0c;下面的装载问题和01背包问题属于子集树的范畴。 解空间类型&#xff1a; 子集树&#xff1…

【C++项目】高并发内存池第七讲性能分析

目录 1.测试代码2.代码介绍3.运行结结果 1.测试代码 #include"ConcurrentAlloc.h" #include"ObjectPool.h" #include"Common.h" void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds) {std::vector<std::thread> vthread(…