Linux内核学习(六)—— 中断(基于Linux 2.6内核)

一、中断

中断使得硬件得以发出通知给处理器。中断随时都可以产生,如键盘敲击就会触发中断,通知操作系统有按键按下。

不同设备对应的中断不同,而每个中断都通过一个唯一的数字标识。这些中断值通常被称为中断请求(IRQ)线。每个 IRQ 线都会关联一个数值量。

异常与中断不同,它在产生时必须考虑与处理器时钟同步,异常也常常被称为同步中断。在处理器执行到错误指令时候(如除数为0),或者是在执行期间出现特殊情况(如缺页),这些异常需要通过内核来处理,处理器就会产生一个异常。中断还可以通过软中断实现系统调用。

二、中断处理程序

在响应一个特定中断的时候,内核会执行一个函数,该函数叫做中断处理程序(interrupt handler) 或中断服务例程(interrupt service routine,ISR)。每种类型的中断都有一个相应的中断处理程序。一个设备的中断处理程序是它设备驱动程序(driver)的一部分——设备驱动程序是用于对设备进行管理的内核代码

中断处理程序与其他内核函数的真正区别在于,中断处理程序是被内核调用来响应中断的,而它们运行于我们称之为中断上下文的特殊上下文中。

中断可能随时发生,因此中断处理程序也就随时可能执行。所以必须保证中断处理程序能够快速执行,这样才能保证尽可能快地恢复中断代码的执行。

一般把中断处理切位两个部分:中断处理程序是上半部(top half)——接收到一个中断,上半部立刻开始执行,但只做有严格时限的工作,例如对接收的中断进行应答或复位硬件,这些工作都是在所有中断被禁止的情况下完成的。能够被允许稍后完成的工作会推迟到下半部(bottom half)去。

 

三、注册中断处理程序

中断处理程序是管理硬件的驱动程序的组成部分。如果设备使用中断,那么相应的驱动程序就注册一个中断处理程序。

驱动程序可以通过 request_irq() 函数注册一个中断处理程序(声明在 <linux/interrupt.h>),并且激活给定的中断线,以处理中断:

第一个参数 irq 表示要分配的中断号。

第二个参数 handler 是一个指针,指向处理这个中断的实际中断处理程序。只要操作系统一接收到中断,该函数就被调用。

注意 handler 函数的原型,它接受两个参数,并有一个类型为 irqreturn_t 的返回值。

第三个参数 flags 可以为 0,也可能是下列一个或多个标志的位掩码。定义在 <linux/interrupt.h>。其中最重要的几个标志是:

  • IRQF_DISABLED——该标志被设置后,意味着内核在处理中断处理程序本身期间,要禁止所有的其他中断。多数中断处理程序是不会设置该位,这种用法留给希望快速执行的轻量级中断。
  • IRQF_TIMER——该标志是特别为系统定时器的中断处理而准备的。
  • IRQF_SHARED——此标志标明可以在多个中断处理程序之间共享中断线。

第四个参数 name 是与中断相关的设备的 ASCII 文本表示

第五个参数 dev 用于共享中断线。当一个中断处理程序需要释放时,dev 将提供唯一的标志信息(cookie),以便从共享中断线的诸多中断处理程序中删除指定的那一个。如果无需共享中断线则设置为 NULL 即可。内核每次调用中断处理程序时,都会把这个指针传递给它。实践中往往会通过它来传递驱动程序的设备结构

request_irq() 函数成功执行会返回 0,非 0 值则代表有错误发生。

request_irq() 函数可能会睡眠,因此不能在中断上下文或其他不允许阻塞的代码中调用该函数。因为 kmalloc() 是可睡眠的。

四、卸载中断处理程序

卸载驱动程序时,需要注销相应的中断处理程序,并释放中断线。上述动作需要调用:

void free_irq(unsigned int irq, void *dev)

如果指定的中断线不是共享的,则删除处理程序的同时将禁用这条中断线。如果中断线是共享的,则删除 dev 所对应的处理程序,并不禁用中断线。

五、编写中断处理程序

以下是一个中断处理程序声明:

static irqreturn_t intr_handler(int irq, void *dev)

中断处理程序的返回值为 irqreturn_t。中断处理程序可能返回两个特殊的值:IRQ_NONE 和 IRQ_HANDLED。当中断处理程序检测到一个中断,但该中断对应的设备并不是在注册处理函数期间指定的产生源的时候,返回 IRQ_NONE。反之则返回 IRQ_HANDLED。

Linux 的中断处理程序是无需重入的。同一个中断处理程序绝不会被同时调用以处理嵌套的中断。

共享的处理程序的特点有:

  • request_irq() 的参数 flags 必须设置 IRQF_SHARED 标志。
  • 对于每个注册的中断处理程序来说,dev 参数必须唯一。指向任一设备结构的指针就是唯一的。
  • 中断处理程序必须能够区分它的设备是否真的产生了中断。

内核在接收一个中断后,它将依次调用在该中断线上注册的共享的处理程序,所以,一个处理程序必须知道它是否应该为这个中断负责,如果与它相关的设备并没有产生中断,那么处理程序应该立即退出。

六、中断上下文

当执行一个中断处理程序的时候,内核处于中断上下文(interrupt context)中。

进程上下文是一种内核所处的操作模式,此时内核代表进程执行。进程上下文可以睡眠,也可以调用调度程序,因为进程有 task_struct 结构,当进程再次被调度时能恢复进程执行环境。

中断上下文和进程没有什么关联,并且中断上下文是不可睡眠的,因为中断上下文没有某种结构记录它的执行状态,一旦睡眠就无法再被重新唤起了(没有东西来恢复它的执行环境),所以在中断上下文中不可使用信号量,因为信号量会导致睡眠。因为中断打断了其他代码的执行,所以中断上下文的代码应该简洁、迅速,尽量把工作从中断处理程序中分离出来,放到下半部执行。

procfs 是一个虚拟文件系统,它只存在于内核内存,一般安装于 /proc 目录。在 procfs 中读写文件都要调用内核函数。/proc/interrupt 文件存放系统中与中断相关的统计信息。

通过禁止中断,可以确保某个中断处理程序不会抢占当前的代码。锁提供保护机制,防止来自其他处理器的并发访问,而禁止中断提供保护机制,则是防止来自其他中断处理程序的并发访问。

禁止当前处理器上的本地中断,随后又激活它们的语句为:

local_irq_disable();
/* 禁止中断 */
local_irq_enable();

x86 上这两个函数是通过单个汇编指令实现的,cli 指令和 sti 指令。

但是上述用法并不安全,万一在调用 local_irq_disable() 之前中断就是关闭的,之后再调用 local_irq_enable()相当于无条件把中断打开了,所以为了更安全的关闭中断,我们使用如下方式:

unsigned long flags;local_irq_save(flags); /* 禁止中断 */local_irq_restore(flags)l /* 中断恢复到原来的状态 */

七、中断下半部(bottom half)

下半部的任务就是执行与中断处理密切相关但中断处理程序本身不执行的工作

  • 对时间敏感的任务,放到上半部。
  • 和硬件相关的任务,放到上半部。
  • 如果一个任务要保证不被其他中断打断,放到上半部。
  • 其他的任务考虑放到下半部。 

上半部执行简单快速,执行时禁止中断。下半部稍后执行,执行时能响应所有中断。这种设计可以使系统处于中断屏蔽状态的时间尽可能短,以此来提高系统的响应能力。

实现下半部的方法有:软中断、 tasklet 和任务队列、。

软中断

软中断是一组静态定义的下半部接口,有32个,可以在所有处理器上同时执行(这里提到的软中断和系统调用所用到的软件中断是不同的概念)。

软中断执行函数如下:

asmlinkage void do_softirq(void)2 {3     __u32 pending;4     unsigned long flags;5  6     /* 判断是否在中断处理中,如果正在中断处理,就直接返回 */7     if (in_interrupt())8         return;9  
10     /* 保存当前寄存器的值 */
11     local_irq_save(flags);
12  
13     /* 取得当前已注册软中断的位图 */
14     pending = local_softirq_pending();
15  
16     /* 循环处理所有已注册的软中断 */
17     if (pending)
18         __do_softirq();
19  
20     /* 恢复寄存器的值到中断处理前 */
21     local_irq_restore(flags);
22 }

代码的第一行判断是否在中断处理中,如果是则立刻退出函数,这说明如果有软中断正在执行,则其他软中断会返回。所以,软中断不能被另外一个软中断抢占!唯一可以抢占软中断的是中断处理程序。虽然不能在本处理器上抢占,但其他的软中断可以在其他处理器上同时运行,所以对于临界区需要加锁保护。

软中断留给对时间要求最严格的下半部使用。目前只有网络,内核定时器和 tasklet 建立在软中断上。

Tasklet 

注意,这第二种机制是基于软中断实现的,灵活性强,动态创建的下半部实现机制。两个不同类型的 tasklet 可以在不同处理器上运行,但相同的不可以,可以通过代码动态注册。

在 SMP 上,调用 tasklet 是会检测 TASKLET_STATE_SCHED 标志,如果同类型在运行,就退出函数。

tasklet 由于是基于软中断实现的,所以也允许响应中断,但不能睡眠。

工作队列

工作队列(work queue)是另外一种将中断的部分工作推后的一种方式,它可以实现一些tasklet不能实现的工作,比如工作队列机制可以睡眠。这种差异的本质原因是,在工作队列机制中,将推后的工作交给一个称之为工作者线程(worker thread)的内核线程去完成(单核下一般会交给默认的线程events/0)。因此,在该机制中,当内核在执行中断的剩余工作时就处在进程上下文(process context)中。也就是说由工作队列所执行的中断代码会表现出进程的一些特性,最典型的就是可以重新调度甚至睡眠。

对于tasklet机制(中断处理程序也是如此),内核在执行时处于中断上下文(interrupt context)中。而中断上下文与进程毫无瓜葛,所以在中断上下文中就不能睡眠。因此,选择tasklet还是工作队列来完成下半部分应该不难选择。当推后的那部分中断程序需要睡眠时,工作队列毫无疑问是你的最佳选择;否则,还是用tasklet吧。

 

 

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

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

相关文章

【观察】戴尔科技:构建企业创新“韧性”,开辟数实融合新格局

过去几年&#xff0c;国家高度重视发展数字经济&#xff0c;将其上升为国家战略。其中&#xff0c;“十四五”规划中&#xff0c;就明确提出要推动数字经济和实体经济的深度融合&#xff0c;以数字经济赋能传统产业转型升级&#xff1b;而2023年年初正式发布的《数字中国建设整…

Coremail参与编制|《信创安全发展蓝皮书——系统安全分册(2023年)》

信创安全发展蓝皮书 近日&#xff0c;Coremail参与编制的《信创安全发展蓝皮书—系统安全分册&#xff08;2023年&#xff09;》重磅发布。 此次信创安全发展蓝皮书由工业和信息化部电子第五研究所联合大数据协同安全技术国家工程研究中心重磅共同发布。 本次蓝皮书涵盖信创系…

多种方法实现 Nginx 隐藏式跳转(隐式URL,即浏览器 URL 跳转后保持不变)

多种方法实现 Nginx 隐藏式跳转(隐式URL,即浏览器 URL 跳转后保持不变)。 一个新项目,后端使用 PHP 实现,前端不做路由,提供一个模板,由后端路由控制。 Route::get(pages/{name}, [\App\Http\Controllers\ResourceController::class, getResourceVersion])

【Python原创设计】基于Python Flask 机器学习的全国+上海气象数据采集预测可视化系统-附下载链接以及详细论文报告,原创项目其他均为抄袭

基于Python Flask 机器学习的全国上海气象数据采集预测可视化系统 一、项目简介二、开发环境三、项目技术四、功能结构五、运行截图六、功能实现七、数据库设计八、源码获取 一、项目简介 在信息科技蓬勃发展的当代&#xff0c;我们推出了一款基于Python Flask的全国上海气象数…

多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测

多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测 目录 多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经…

Centos 解决 XXX不在 sudoers 文件中。此事将被报告。的错误

本来想使用 sudo 拷贝一个文件&#xff0c;结果出现上面的问题&#xff01; 下面是解决方法&#xff1a; 首先登录root&#xff0c;然后执行下面的命令 vim /etc/sudoers 将你需要添加的用户带红色框线的地方&#xff0c;模仿root写一遍&#xff0c;然后保存&#xff01; …

分类预测 | MATLAB实现BWO-TCN-Attention数据分类预测

分类预测 | MATLAB实现BWO-TCN-Attention数据分类预测 目录 分类预测 | MATLAB实现BWO-TCN-Attention数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.BWO-TCN-Attention数据分类预测程序&#xff1b; 2.无Attention适用于MATLAB 2022b版及以上版本&#xf…

Elasticsearch算分优化方案之rescore_query

简介 今天来说一说Elasticsearch 的重新评分&#xff0c;即在检索出来一次结果的基础上在进行检索提升数据排序效果&#xff0c;但是仅对查询或者post_filter阶段返回的前多少条进行二次查询。在每个分片上进行二次检索的文档数量时可以通过window_size 控制的&#xff0c;该参…

2019年3月全国计算机等级考试真题(C语言二级)

2019年3月全国计算机等级考试真题&#xff08;C语言二级&#xff09; 第1题 负责数据库中查询操作的数据库语言是 A. 数据定义语言 B. 数据管理语言 C. 数据操纵语言 D. 数据控制语言 正确答案&#xff1a;C 第2题 有关系如下图所示&#xff0c;其违反了哪一类完整性约束 …

2023国赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

【Python原创设计】基于Python Flask的上海美食信息与可视化宣传网站项目-附下载方式以及往届优秀论文,原创项目其他均为抄袭

基于Python Flask的上海美食信息与可视化宣传网站&#xff08;获取方式访问文末官网&#xff09; 一、项目简介二、开发环境三、项目技术四、功能结构五、运行截图六、功能实现七、数据库设计八、源码获取 一、项目简介 随着大数据和人工智能技术的迅速发展&#xff0c;我们设…

论文速递 Nature 2023 | Heat-assisted detection and ranging

注1:本文系“计算成像最新论文速览”系列之一,致力于简洁清晰地介绍、解读非视距成像领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, SIGGRAPH, TPAMI; Light‐Science & Applications, Optica 等)。 本次介绍的论文是: 2023年,Nature,“…

31.Netty源码之客户端启动流程

highlight: arduino-light 客户端启动主要流程 如果看了服务器端的启动流程&#xff0c;这里简单看下就可以了。 java package io.netty.server; ​ import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import …

A. Two Semiknights Meet

题目描述 可知走法为中国象棋中的象的走法 解题思路 利用结构体来存储两个 K K K的位置 x , y x,y x,y&#xff0c;因为两个 K K K同时走&#xff0c;所以会出现两种情况 相向而行&#xff0c;两者距离减少 相反而行&#xff0c;两者距离不变 我们完全可以不考虑格子是好…

【C#学习笔记】C#特性的继承,封装,多态

文章目录 封装访问修饰符静态类和静态方法静态构造函数 继承继承原则sealed修饰符里氏替换原则继承中的构造函数 多态接口接口的实例化 抽象类和抽象方法抽象类和接口的异同 虚方法同名方法new覆盖的父类方法继承的同名方法 运行时的多态性编译时的多态性 照理继承封装多态应该…

C++笔记之std::move和右值引用的关系、以及移动语义

C笔记之std::move和右值引用的关系、以及移动语义 code review! 文章目录 C笔记之std::move和右值引用的关系、以及移动语义1.一个使用std::move的最简单C例子2.std::move 和 T&& reference_name expression;对比3.右值引用和常规引用的经典对比——移动语义和拷贝语…

Go语言入门指南:基础语法和常用特性解析(上)

一、Go语言前言 Go是一种静态类型的编译语言&#xff0c;常常被称作是21世纪的C语言。Go语言是一个开源项目&#xff0c;可以免费获取编译器、库、配套工具的源代码&#xff0c;也是高性能服务器和应用程序的热门选择。 Go语言可以运行在类UNIX系统——比如Linux、OpenBSD、M…

Red Hat Enterprise Linux (RHEL) 6.4 安装、redhat6.4安装

1、下载地址 Red Hat Enterprise Linux (RHEL) 6.4 DVD ISO 迅雷下载地址http://rhel.ieesee.net/uingei/rhel-server-6.4-x86_64-dvd.iso 2、创建虚拟机 3、redhat安装 选择第一个安装 Skip跳过检查 语言选择简体中文 键盘选择默认 选择基本存储设备 忽略所有数据 设置root密…

【ECCV2022】Swin-Unet: Unet-like Pure Transformer for Medical Image Segmentation

Swin-Unet: Unet-like Pure Transformer for Medical Image Segmentation 论文&#xff1a;https://arxiv.org/abs/2105.05537 代码&#xff1a;https://github.com/HuCaoFighting/Swin-Unet 解读&#xff1a;Swin-UNet&#xff1a;基于纯 Transformer 结构的语义分割网络 -…

并查集及其简单应用

文章目录 一.并查集二.并查集的实现三.并查集的基本应用 一.并查集 并查集的逻辑结构:由多颗不相连通的多叉树构成的森林(一个这样的多叉树就是森林的一个连通分量) 并查集的元素(树节点)用0~9的整数表示,并查集可以表示如下: 并查集的物理存储结构:并查集一般采用顺序结构实…