Linux驱动开发——(八)Linux异步通知

目录

一、异步通知简介

二、信号处理

2.1 驱动程序中的处理

2.1.1 fasync_struct结构体

2.1.2 fasync操作函数

2.1.3 kill_fasync函数

2.2 应用程序中的处理

三、驱动代码


一、异步通知简介

异步通知的核心就是信号。信号类似于硬件上使用的中断,只不过信号是软件层次上的,算是在软件层次上对中断的一种模拟。

驱动可以通过主动向应用程序发送信号的方式来报告自己可以访问,应用程序获取到信号以后就可以从驱动设备中读取或者写入数据。整个过程就相当于应用程序收到了驱动发送过来了的一个“中断“,然后应用程序去响应这个”中断“。在整个处理过程中应用程序并没有去查询驱动设备是否可以访问,一切都是由驱动设备自己告诉给应用程序的。arch/xtensa/include/uapi/asm/signal.h文件中定义了Linux所支持的所有信号:

#define SIGHUP 1 /* 终端挂起或控制进程终止 */ 
#define SIGINT 2 /* 终端中断(Ctrl+C组合键) */ 
#define SIGQUIT 3 /* 终端退出(Ctrl+\组合键) */ 
#define SIGILL 4 /* 非法指令 */ 
#define SIGTRAP 5 /* debug使用,有断点指令产生 */ 
#define SIGABRT 6 /* 由abort(3)发出的退出指令 */ 
#define SIGIOT 6 /* IOT指令 */ 
#define SIGBUS 7 /* 总线错误 */ 
#define SIGFPE 8 /* 浮点运算错误 */ 
#define SIGKILL 9 /* 杀死、终止进程 */ 
#define SIGUSR1 10 /* 用户自定义信号1 */ 
#define SIGSEGV 11 /* 段违例(无效的内存段) */ 
#define SIGUSR2 12 /* 用户自定义信号2 */ 
#define SIGPIPE 13 /* 向非读管道写入数据 */ 
#define SIGALRM 14 /* 闹钟 */ 
#define SIGTERM 15 /* 软件终止 */ 
#define SIGSTKFLT 16 /* 栈异常 */ 
#define SIGCHLD 17 /* 子进程结束 */ 
#define SIGCONT 18 /* 进程继续 */ 
#define SIGSTOP 19 /* 停止进程的执行,只是暂停 */	
#define SIGTSTP 20 /* 停止进程的运行(Ctrl+Z组合键) */ 
#define SIGTTIN 21 /* 后台进程需要从终端读取数据 */ 
#define SIGTTOU 22 /* 后台进程需要向终端写数据 */ 
#define SIGURG 23 /* 有"紧急"数据 */ 
#define SIGXCPU 24 /* 超过CPU资源限制 */ 
#define SIGXFSZ 25 /* 文件大小超额 */ 
#define SIGVTALRM 26 /* 虚拟时钟信号 */ 
#define SIGPROF 27 /* 时钟信号描述 */ 
#define SIGWINCH 28 /* 窗口大小改变 */ 
#define SIGIO 29 /* 可以进行输入/输出操作 */ 
#define SIGPOLL SIGIO 
#define SIGPWR 30 /* 断点重启 */ 
#define SIGSYS 31 /* 非法的系统调用 */ 
#define SIGUNUSED 31 /* 未使用信号 */ 

在这些信号中,除了 SIGKILL(9)和 SIGSTOP(19)这两个信号不能被忽略外,其他的信号都可以忽略。驱动程序可以通过向应用程序发送不同的信号以实现不同的功能。


二、信号处理

2.1 驱动程序中的处理

2.1.1 fasync_struct结构体

首先要定义一个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; 
};
2.1.2 fasync操作函数

然后在设备驱动中实现file_operations操作集中的fasync操作函数

int (*fasync) (int fd, struct file *filp, int on)

fasync函数里一般通过调用fasync_helper函数以初始化前面定义的fasync_struct结构体指针

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

fasync_helper函数的前三个参数即fasync函数的三个参数,第四个参数是要初始化的fasync_struct结构体指针变量。 在关闭驱动文件的时候需要在file_operations操作集中的release操作函数中释放fasync_struct,fasync_struct的释放函数同样是fasync_helper

所以驱动中有关fasync操作函数的模板代码大致如下:

struct xxx_dev { 
    ...... 
    struct fasync_struct *async_queue; /* 异步相关结构体 */ 
}; 
 
static int xxx_fasync(int fd, struct file *filp, int on) 
{ 
    struct xxx_dev *dev = (xxx_dev)filp->private_data; 

    if (fasync_helper(fd, filp, on, &dev->async_queue) < 0) 
        return -EIO; 
    return 0; 
} 

static struct file_operations xxx_ops = { 
    ...... 
    .fasync = xxx_fasync, 
    ...... 
};

static int xxx_release(struct inode *inode, struct file *filp) 
{ 
    return xxx_fasync(-1, filp, 0); /* 删除异步通知 */ 
}
2.1.3 kill_fasync函数

当设备可以访问的时候,kill_fasync函数负责发送指定的信号,相当于产生“中断”:

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

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

2.2 应用程序中的处理

应用程序应根据驱动程序所使用的信号来设置相应信号的处理函数,应用程序使用signal函数来设置信号的处理函数。然后使用fcntl(fd, F_SETOWN, getpid())将本应用程序的进程号告诉给内核以开启异步通知:

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

重点是通过fcntl函数设置进程状态为FASYNC——驱动程序中的fasync操作函数会因此而执行。


三、驱动代码

以Linux驱动开发——(六)按键中断实验的驱动代码为模板修改。

添加头文件和相关变量:

#include <linux/fcntl.h>

struct fasync_struct *async_queue;

在定时器服务函数里添加:

if(atomic_read(&dev->releasekey)) {  
    if(dev->async_queue) 
    kill_fasync(&dev->async_queue, SIGIO, POLL_IN); 
}

添加fasync操作函数:

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

static struct file_operations imx6uirq_fops = { 
    .fasync = imx6uirq_fasync, 
};

完善release操作函数:

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

static struct file_operations imx6uirq_fops = {  
    .release = imx6uirq_release, 
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【海博】雅思该怎么考?

文章目录 考试类型 考试内容 考试形式 备考资源 考试报名 考试成绩 考试类型 学术类&#xff08;A类&#xff09;适用于&#xff1a;出国留学申请本科&#xff0c;研究生及以上学位&#xff0c;或获得专业资质。学术类考试评估考生的英语水平是否满足进行大学或研究生学习…

【C语言】文件操作(1)

为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久化的…

Sylar C++高性能服务器学习记录07 【协程模块-知识储备篇】

早在19年5月就在某站上看到sylar的视频了&#xff0c;一直认为这是一个非常不错的视频&#xff0c;由于本人一直是自学编程&#xff0c;基础不扎实&#xff0c;也没有任何人的督促&#xff0c;没能坚持下去&#xff0c;每每想起倍感惋惜。恰逢互联网寒冬&#xff0c;在家无事&a…

vim 插件01:插件管理神器pathogen

1、pathogen简介 Vim 插件 pathogen 是一款历史比较悠久的 Vim 插件管理器。Pathogen 的主要功能是提供一种模块化的方式来管理和加载 Vim 插件。说人话&#xff1a;vim是一款管理各类插件的插卡&#xff0c;使用它会让插件的安装和使用非常方便。 以下是 Pathogen 的主要特点…

【大模型应用篇5】应对裁员潮,突发奇想,打造“收割offer”智能体.......

前段时间飞书大裁员, 不禁让人感到危机四伏,加上《【大模型应用篇4】普通人构建智能体的工具》之前文章介绍了普通人打造智能体的工具, 这节课就带大家利用字节产品coze构建“程序员智能体”, 方便应对裁员,随时做好找工作的准备.打造一款面试智能体,方便各位程序员面试, 这个智…

错误代码126:加载d3dcompiler_43.dll失败,分享多种解决方法

在正常使用电脑的过程中&#xff0c;当我尝试启动并运行一款心仪的游戏时&#xff0c;系统却突然弹出一个令人困扰的错误提示“错误代码126:加载d3dcompiler_43.dll失败”&#xff0c;它会导致游戏无法正常运行。为了解决这个问题&#xff0c;我经过多次尝试和总结&#xff0c;…

22年全国职业技能大赛——Web Proxy配置(web 代理)

前言&#xff1a;原文在我的博客网站中&#xff0c;持续更新数通、系统方面的知识&#xff0c;欢迎来访&#xff01; 系统服务&#xff08;22年国赛&#xff09;—— web Proxy服务&#xff08;web代理&#xff09;https://myweb.myskillstree.cn/114.html 目录 RouterSrv …

OGG extract进程占据大量虚拟内存导致服务器内存异常增长分析

现象 oracle服务器一节点内存&#xff0c;一个月来持续升高&#xff0c;近一月上涨10%左右。 问题分析 OS内存使用情况 使用内存最大的10个进程如下&#xff0c;PID为279417占用最大的内存。 查询279417&#xff0c;发现是ogg相关进程。 发现ogg的extract进程占用了大量的虚拟内…

软件测试(Web自动化测试)(二)

一.Selenium WebDriver的基本应用 &#xff08;一&#xff09;安装浏览器驱动 1.关闭浏览器的自动更新功能 以Windows7&#xff08;64位&#xff09;操作系统为例&#xff0c;讲解如何关闭Chrome浏览器的自动更新。首先按下快捷键“WinR”&#xff0c;打开运行对话框&#x…

【备战软考(嵌入式系统设计师)】02-计算机指令

指令集 我们计算机要执行程序&#xff0c;本质上是执行一条条的指令&#xff0c;而指令是从指令集中取出的&#xff0c;目前常见的指令集有CISC&#xff08;Complex Instruction Set Computer&#xff0c;复杂指令集&#xff09;和RISC&#xff08;Reduced Instruction Set Co…

2024最新智慧医疗智慧医院大数据展示,医院数据采集概况、医院指标分析、医院就诊趋势分析等。源代码免费下载。

系列文章目录 【复制就能用1】2分钟玩转轮播图,unslider的详细用法 【复制就能用2】css实现转动的大风车&#xff0c;效果很不错。 【复制就能用3】2分钟自己写小游戏&#xff1a;剪刀石头布小游戏、扫雷游戏、五子棋小游戏 【复制就能用4】2024最新智慧医疗智慧医院大数据…

c++并查集

文章目录 前言一、并查集1、并查集原理2、并查集实现3、并查集应用1.省份数量2.等式方程的可满足性 前言 一、并查集 1、并查集原理 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后…

应急行业的智能安全帽(高端)

前面介绍了低端、中端安全帽&#xff0c;接着再讲讲高端安全帽。做高端安全帽的企业非常少&#xff0c;估计一只手都数的出来。确实也和智能安全帽这个领域体量有关系&#xff0c;并且他有一个新的“劲敌”——智能眼镜从其他领域瓜分原属于他的市场&#xff0c;这些都是题外话…

SpringBoot引入Layui样式总是出现404

一般出现Layui样式文件如css&#xff0c;js404的错误 解决方案 &#xff08;1&#xff09;首先将其中的静态资源下载resources/static中 &#xff08;2&#xff09;在启动类中重写方法 package com.gq.booksystem;import org.mybatis.spring.annotation.MapperScan; import …

【ETAS CP AUTOSAR工具链】RTE层基本概念与开发流程

本篇文章续接上篇文章【ETAS CP AUTOSAR工具链】基本概念与开发流程&#xff0c;继续按上篇文章描述的ETAS CP工具链进行开发的基本框架&#xff0c;讲述了“RTE集成与配置”这部分的基本概念与开发流程。 RTE&#xff08;Runtime Environment&#xff09;处于应用层与基础软件…

【Godot4.2】自定义Todo清单类 - myTodoList

概述 在写myList类的时候&#xff0c;就想到可以写一个类似的Todo清单类。 基础思路 本质还是在内部维护一个数组&#xff0c;在其基础上进行增删改查操作的封装为了方便存储数据&#xff0c;编写一个自定义内置类TodoItem&#xff0c;内部数组就变成了Array[TodoItem]类型的…

Git | 远程操作

Git | 远程操作 文章目录 Git | 远程操作0、分布式版本控制系统概念1、创建远程仓库2、克隆远程仓库https方式ssh方式 3、推送至远程仓库4、本地拉取远程仓库5、配置Git忽略特殊文件给命令配置别名 6、标签管理创建标签操作标签 0、分布式版本控制系统概念 Git是一个分布式版本…

Git--分布式版本控制系统

目录 一、理解分布式版本控制系统二、远程仓库三、克隆远程仓库四、向远程仓库推送五、拉取远程仓库六、配置Git七、给命令配置别名八、创建标签九、操作标签 一、理解分布式版本控制系统 我们⽬前所说的所有内容&#xff08;⼯作区&#xff0c;暂存区&#xff0c;版本库等等&a…

24深圳杯AC题完整思路+可执行代码+参考论文!!!!

比赛题目的完整版思路可执行代码数据参考论文都会在第一时间更新上传的&#xff0c;大家可以参考我往期的资料&#xff0c;所有的资料数据以及到最后更新的参考论文都是一次付费后续免费的。注意&#xff1a;&#xff08;建议先下单占坑&#xff0c;因为随着后续我们更新资料数…

three.js 学习笔记 | 光线投射技术 - 包围盒(碰撞检测)

文章目录 three.js 学习笔记光线投射技术实现3D场景交互事件 THREE.Raycaster坐标系的转换案例&#xff1a;选中的模型变为红色 包围盒Box3 - 碰撞检测AABB包围盒辅助器Box3Helper案例1&#xff1a;创建AABB包围盒/包围球computeBoundingBox与boundingBox 搭配使用&#xff0c;…