驱动开发系列04-中断处理

目录

一:概述

二:启用中断

三:注册中断处理程序 

四:自动检测中断号

五:快中断与慢中断

六:中断处理程序

 七:处理参数和返回值

八:禁用中断

九:上半部和下半部

Tasklets

Workqueues

十:共享中断

               


一:概述

       虽然有时候只需使用I/O端口就能控制设备了,但大多数实际的设备都要更复杂一些。设备必须与外界交互,通常包括磁盘旋转、磁带移动、跨电缆的远距离数据传输等。很多外界交互需要花费多个处理器周期才能完成,速度要比处理器慢得多。让处理器等待外部事件完成几乎总是不可取的,因此必须有一种方式,让设备在发生事件时,或事件处理完成时通知处理器。 而这种通知的方式就是中断。

        中断是设备给处理器发送的一个信号,以便让处理器留意和处理。Linux处理中断的方式与其用户空间处理信号的方式基本相同。对于大多数驱动程序来说,只需为其设备的中断注册一个处理程序,并在中断到达时正确地处理它们即可。当然,在这个简单的逻辑之下,还隐藏一些复杂性;特别是,由于中断处理程序的运行方式不用,中断处理程序所能执行的操作也有一定的限制。

        如果没有真正的硬件设备来产生中断,就很难演示中断的使用。因此,本文中使用的示例代码是与并口(parallel port)一起工作的。在现代硬件中,这种端口已经开始变得稀缺,但幸运的是,大多数人在他们的系统上仍然能够获得可用的端口(实际上在现在电脑上,并口已被USB接口所取代,没有并口的情况下,可以用一根USB转并口线代替)。我们将用一个称为“short”的示例;来演示并口中断的产生和处理。示例名字之所以叫 “short”, 实际上不是 short int 的意思,它是(Simple Hardware Operations and Raw Tests)的简写, 以提醒我们它可以处理中断。

       不过,在进入主题之前,我需要提醒大家注意一点。中断处理程序的本质是与其他代码同时运行。因此,它们不可避免地会引发并发问题以及数据结构和硬件的争用问题。如果不熟悉Linux并发技术的朋友,我建议你回头查下并发的相关资料。因为在中断工作时,对并发控制技术的理解至关重要。

二:启用中断

       并口可以触发中断。打印机利用这一功能通知打印机驱动程序,准备接受缓冲区中的下一个字符。

      与大多数设备一样,并口在不启用中断之前实际上不会产生中断;并口标准规定,设置端口 2 的第 4 位(0x37a、0x27a 或其他)可启用中断。在模块初始化时,short例子会通过outb来设置该位。 

       一旦启用中断,并口的第 10 针电信号(即所谓的 ACK 位)就会从低电平变为高电平时产生中断。强制接口产生中断的最简单方法(除非将打印机连接到端口)是将并行连接器的第 9 针和第 10 针连接在一起。

三:注册中断处理程序 

        如果你想真正 “看到 ”中断的产生,仅仅在硬件中启动中断是不够的,还必须在Linux系统中配置一个中断处理程序。如果没有被告知Linux 内核要待你的中断,那么它只会忽略它。

        在Linux系统中,中断线是一种宝贵且有限的资源,尤其是在只有 15 或 16 条中断线的情况下。内核保存着一个中断线注册表,类似于 I/O 端口注册表。模块在使用中断线(或 IRQ,表示中断请求)之前,应先请求该中断线,并在使用完毕后释放该中断线。在许多情况下,模块还需要与其他驱动程序共享中断线,在<linux/interrupt.h> 中声明了中断线注册函数,释放中断线函数:

int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),unsigned long flags,const char *dev_name,void *dev_id);
void free_irq(unsigned int irq, void *dev_id);

         request_irq 函数的返回值值要么是 0(表示成功),要么是负(表示错误代码)。函数返回 -EBUSY 表示另一个驱动程序已经在使用请求的中断线,这种情况并不少见。函数的参数如下:

        unsigned int irq
        表示请求的中断(线)编号。
        irqreturn_t (*handler)(int, void *, struct pt_regs *)
        表示中断处理程序的函数指针。本章稍后将讨论该函数的参数及其返回值。
        unsigned long flags
        表示一个与中断管理相关的掩码(稍后描述)。
        const char *dev_name
         传递给 request_irq 的字符串, 用于在 /proc/interrupts 中显示中断的所有者(参见下一节)。
        void* dev_id
         表示共享中断线的指针。它是一个唯一标识符,在释放中断线时使用,也可被驱动程序用于指向其私有数据区(用于识别正在中断的设备)。如果中断不是共享的,dev_id 可以设置为 NULL,但无论如何,使用该项指向设备结构体是个好主意。我们将在后面一节中看到 dev_id 的实际用途。

        标志位(flags)可设置的位数如下:

        SA_INTERRUPT
        表示 “快速 ”中断处理程序。快速处理程序是在当前处理器禁用中断的情况下执行的(“快速和慢速处理程序 ”一节将介绍该主题)。
        SA_SHIRQ
        表示中断可在设备间共享。共享的概念在 “中断共享 ”一节中概述。
        SA_SAMPLE_RANDOM
        该位表示生成的中断可以为 /dev/random 和 /dev/urandom 使用的熵池作出贡献。这些设备在读取时会返回真正的随机数,旨在帮助应用软件选择安全的加密密钥。这些随机数是从由各种随机事件贡献的熵池中提取的。如果设备在真正随机的时间产生中断,则应设置此标志。相反,如果您的中断是可预测的(例如,帧捕捉器的垂直消隐),则不值得设置该标记--反正它也不会对系统熵做出贡献。可能受攻击者影响的设备不应设置此标记;例如,网络驱动程序可能会受到来自外部的可预测数据包定时的影响,因此不应为熵池做出贡献。更多信息,请参阅 drivers/char/random.c 中的注释。

       中断处理程序可以在驱动程序初始化时安装,也可以在设备首次打开时安装。虽然在模块的初始化函数中安装中断处理程序听起来是个好主意,但通常并非如此,尤其是在设备不共享中断的情况下。因为中断线路的数量是有限的,所以不能浪费它们。电脑中的设备数量很容易超过中断数量。如果一个模块在初始化时请求一个 IRQ,它将阻止任何其他驱动程序使用该中断,即使持有该中断的设备从未被使用过。如果在设备打开时请求中断,则可以共享中断线。

       调用 request_irq 的正确位置是设备首次打开时,即在设备产生中断之前。调用 free_irq 的位置是设备最后一次关闭时,即设备被告知不再产生中断之后。这种技术的缺点是需要保持每个设备的打开次数,以便知道何时可以禁用中断。

        尽管进行了上述讨论,但 short 示例还是在加载时请求中断。因此,short 在其初始化函数(short_init)中请求中断,而不是像真正的驱动程序那样在 short_open 中请求中断。

if (short_irq >= 0) {result = request_irq(short_irq, short_interrupt,SA_INTERRUPT, "short", NULL);if (result) {printk(KERN_INFO "short: can't get assigned irq %i\n",short_irq);short_irq = -1;}else { /* actually enable it -- assume this *is* a parallel port */outb(0x10,short_base+2);}
}

         值得一提的是,i386 和 x86_64 体系结构定义了一个查询中断线是否可用的函数:

int can_request_irq(unsigned int irq, unsigned long flags);

        如果中断的尝试分配成功,该函数将返回一个非零值。

四:自动检测中断(线)号

        对于驱动程序来说&#x

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

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

相关文章

事务失效的几种情况

一、事务管理的基本概念 事务有四个重要特性&#xff0c;称为ACID特性&#xff1a; Atomicity(原子性)&#xff1a;事务中的所有操作要么全部完成&#xff0c;要么全部不完成。Consistency(一致性)&#xff1a;事务完成后&#xff0c;数据要处于一致的状态Isolation(隔离性)&…

如何在电脑上演示手机上APP,远程排查移动端app问题

0序&#xff1a; 对接客户&#xff0c;给领导演示移动端产品&#xff0c;或者远程帮用户排查移动端产品的问题。都需要让别人能够看到自己在操作手机。 会议室可以使用投屏&#xff0c;但需要切换电脑和手机。 排查问题经常都是截图、或者手机上录制视频&#xff0c;十分繁琐…

Windows图形界面(GUI)-DLG-C/C++ - 滑动条(Trackbar)

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​​​​链接点击跳转博客主页 目录 滑动条(Trackbar) 使用场景 初始控件 控件消息 示例代码 滑动条(Trackbar) 使用场景 音量控制 亮度调节 视频播放进度控制 任何需要用户在特定范围内选择值的场景 初始控…

恶补,先验分布,后验分布 ,似然估计

恶补&#xff0c;打一遍增加印象 先验分布后验分布&#xff0c;似然估计 声明&#xff1a;仅记录个人学习&#xff0c;并无其他用途。 先验分布 后验分布&#xff0c; 似然估计 隔壁小哥的故事&#xff1a; 隔壁小哥要去15公里外的一个公园里玩&#xff0c;小哥可以选择步行…

【BUG】已解决:ModuleNotFoundError: No module named ‘PIL‘

已解决&#xff1a;ModuleNotFoundError: No module named ‘PIL‘ 目录 已解决&#xff1a;ModuleNotFoundError: No module named ‘PIL‘ 【常见模块错误】 错误原因&#xff1a; 解决办法&#xff1a; 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我…

离散型随机变量为何不是左连续?

目录 离散型随机变量 引言 离散型随机变量的定义和性质是什么&#xff1f; 定义 性质 如何证明离散型随机变量的分布函数在每个可能取值处不具有左连续性&#xff1f; 离散型随机变量的阶梯状分布函数是如何影响其左连续性的&#xff1f; 在统计学中&#xff0c;有哪些方…

web前端面向对象面试25题

1 . 简述面向对象&#xff1f;主要特征是什么&#xff1f; 参考回答&#xff1a; 面向对象是一种对现实世界理解和抽象的方法&#xff0c;是计算机编程技术发展到一定阶段后的产物&#xff0c;是一种是软件开发方法面向对象主要有四大特性&#xff1a; 1、抽象 忽略一个主题中…

微信小程序-自定义组件生命周期

一.created 组件实例创建完毕调用。定义在lifetimes对象里。 不能在方法里面更改data对象里面的值&#xff0c;但是可以定义属性值。 lifetimes:{//不能给data设置值created(){this.testaaconsole.log("created") }}二. attached 模板解析完成挂载到页面。 可以更…

Gitee 使用教程1-SSH 公钥设置

一、生成 SSH 公钥 1、打开终端&#xff08;Windows PowerShell 或 Git Bash&#xff09;&#xff0c;通过命令 ssh-keygen 生成 SSH Key&#xff1a; ssh-keygen -t ed25519 -C "Gitee SSH Key" 随后摁三次回车键&#xff08;Enter&#xff09; 2、查看生成的 SSH…

Carousel of Combinations

由圆排列的公式&#xff0c;不难有 C ( n , k ) ( k n ) k ! k C(n,k)(_k^n)\times \frac{k!}{k} C(n,k)(kn​)kk!​ 于是答案为 ∑ i 1 n ∑ j 1 i ( ( j i ) ⋅ ( j − 1 ) ! ) m o d j \sum_{i1}^{n}\sum_{j1}^{i}((_j^i)\cdot (j-1)!)mod\space j ∑i1n​∑j1i​((ji​…

React学习笔记(井字棋游戏)

本教程将引导你逐步实现一个简单的井字棋游戏&#xff0c;并且不需要你对 React 有任何了解。在此过程中你会学习到一些编写 React 程序的基本知识&#xff0c;完全理解它们可以让你对 React 有比较深入的理解。 教程分成以下几个部分&#xff1a; 配置 是一些准备工作。 概…

【Linux服务器Java环境搭建】010在linux中安装Redis,以及对Redis的配置与远程连接

系列文章目录 【Linux服务器Java环境搭建】 前言 好久没有更新博客了&#xff0c;今天下了班回到家&#xff0c;看到电脑桌上尘封已久的《Spring Boot应用开发实战》&#xff0c;翻开目录想起来之前写的系列【Linux服务器Java环境搭建】还未完结&#xff0c;那就继续吧&#…

实现异步天气数据获取与Spring缓存集成

你好呀&#xff0c;我是小邹。 在Web应用中&#xff0c;实时天气数据的获取是一个常见的需求&#xff0c;特别是在需要频繁更新天气信息的场景下&#xff0c;如旅游网站、天气应用或任何需要展示地理位置相关天气的应用。然而&#xff0c;频繁的外部API调用不仅会增加服务器的…

生成式AI的未来:对话的艺术与代理的实践

生成式 AI 的发展方向&#xff0c;是 Chat 还是 Agent&#xff1f; 随着生成式AI技术的不断进步&#xff0c;关于其未来发展方向的讨论也愈发激烈。究竟生成式AI的未来是在对话系统&#xff08;Chat&#xff09;中展现智慧&#xff0c;还是在自主代理&#xff08;Agent&#x…

操作系统知识点详情-任务调度

本文目录 一、名词解释1. 调度器2. 优先级&#xff08;1&#xff09;优先级反转&#xff08;2&#xff09;优先级继承协议&#xff08;3&#xff09;优先天花板 3. 任务状态&#xff1a;新建、就绪、运行、阻塞、终止。4. 任务类型&#xff1a;计算密集型、I/O密集型5. 实时任务…

virsh命令使用笔记

远程查看 virsh -c qemutcp://root192.168.1.102:16510/system list --all 网络配置 virsh net-define net-name.xml 定义网络 virsh net-dumpxml net-name 当前网络xml virsh net-start net-name 启动网络 virsh net-autostart net-name 自启动网络 virsh net-destr…

HDU1011——Starship Troopers(树形DP),HDU1012——u Calculate e,HDU1013——Digital Roots

目录 HDU1011——Starship Troopers&#xff08;树形DP&#xff09; 题目描述 运行代码 代码思路 树形DP HDU1012——u Calculate e 题目描述 运行代码 代码思路 HDU1013——Digital Roots 题目描述 超时代码 改进后依旧超时代码 运行代码 代码思路 HDU1011——…

前端转base64格式的字体图标方法

1.将需要的字体图标包下载到本地 2.访问 transfonter.org 将字体图标转成base64格式 如 这样就可以和正常的字体图标一样使用了

【Git】Git Submodules 介绍(通俗易懂,总结了工作完全够用的 submodule 命令)

Git Submodules 介绍 1、为什么你值得读这篇文章&#xff1f;2、为什么有 submodules&#xff1f;3、了解 Git Submodules3.1、如何让一个Git仓库变为另一个Git仓库的 submodule3.2、submodule 的父子关系存在哪里3.3、submodule 的父子关系信息怎么存 4、submodule 开发常用操…

【SpringBoot】分页查询

1. Controller ApiOperation("分页查询")GetMapping("/page")public Result<PageResult> pageResultResult(EmployeePageQueryDTO employeePageQueryDTO) {System.out.println(employeePageQueryDTO.toString());PageResult pageResult employeeSer…