windows驱动开发-中断(一)

中断是windows中最难的一部分,这是因为中断本身属于操作系统的一部分,理解了中断和内存,对整个系统也就了解了。

中断部分会先从中断优先级、中断处理、中断服务例程入手,大概讲述一下中断的概念;接着从中断的一般实现来讲解;最后我们会实际分析PCI中断相关的部分。

中断优先级

再看中断之前,我们闲了接一下中断优先级的概念,在之前我们也提到过内核代码的执行级别,那个时候只是简单的说一下代码的运行级别,但实际上,这个概念是中断优先级才对。

windows使用0~31的优先级来描述中断,数值越大,中断优先级越高,详细的描述如下:

PASSIVE_LEVEL 	0 
APC_LEVEL 		1 
DISPATCH_LEVEL 	2 DIRQL: from 3 to 26 for device ISRPROFILE_LEVEL 	27
SYNCH_LEVEL 	28
CLOCK_LEVEL     28
IPI_LEVEL 		29
POWER_LEVEL 	30
HIGH_LEVEL 		31

0~2级别的中断称为软件中断,它们定义在内核代码中;剩下称为硬件中断,定义在HAL(硬件抽象)层中;硬件中断的3~26号称为设备中断,是给windows设备使用的;27~31号中断是留给处理器使用的中断。

HIGH_LEVEL是最高级别的中断,用于一些不可中断的执行过程,比如说,当发生蓝屏的时候,windows会将优先级提升到HIGH_LEVEL;

POWER_LEVEL是电源中断,但是windows中并没有使用它;     

IPI_LEVEL是同步处理器之间通讯的中断;     

CLOCK_LEVEL 是时钟中断,CPU利用这个中断来实现定时器;       

PROFILE_LEVEL是性能剖析中断,在windows进行性能剖析的时候使用;     

Device IRQL则是设备驱动程序使用的,它们可以和设备提供的中断服务例程;

代码运行在某个优先级,是指代码在运行的时候,内核会将优先级提高到某个优先级,事实上,综合前面的部分,我们很容易得到结论,这个说法指的是软件中断,而非硬件中断,不过要注意,内核函数的说明中会明确指出代码运行的优先级,要注意这一点。

3~26的中断等级是设备驱动程序使用的,它们并不是按照加载到内核的顺序确认的,事实上,除了总线驱动,一般也不需要考虑这个问题,不过我们仍然可以在设备管理器中看到一点踪迹:

b1b50be19faa4a789e2b2b222e8daeab.png

这是我从设备管理器中的截图,在USB 3.1总线上,会有一个资源选项卡,其中会给出当前总线的IRQ,这个IRQ后面会被映射为某个IRQL。

在上图中已经能够推断出这个USB总线的寄存器范围是84500000~8450FFFF,它的大小就是0xFFFF;其次,这个设备注册的中断服务例程IRQL等级是20;

实际上,现在内部总线几乎都是PCI总线,大部分都在PCI复合设备上,系统中另外一个中断来源则是GPIO。

中断的处理

Intel x86定义了256个中断向量,这些中断向量通过中断描述符来表达,这些描述符存在中断描述符表IDT中,中断描述符寄存器会在启动后,中断向量编程完成后存储中断描述符表的地址,在中断发生时,控制权转移到中断服务例程执行。

注意,虽然只有256个中断,但是处理器可以处理的中断数非常多,因为在中断描述符表中,32!256号中断对应的是一个中断处理链,同级别的中断可能来自于不同的设备,例如USB总线上的N个设备,可能都挂到一个中断处理例程上。

举个例子,当用0来做除数的时候,在译码周期会被检测到,此时CPU就会将根据异常来将中断向量中0号中断地址从IDTR中取出,将寄存器、栈保存下来,然后跳转到中断的入口点,执行中断,执行完中断之后,再跳回原来的指令流。在这种过程中,我们会发现,保存当前寄存器和栈是希望这个中断可以被处理,异常和中断都是用同一套机制来处理的。

先说异常,对于异常,有三种可能: 错误、异常、终止:

对于错误,处理器期待可以恢复,故处理完之后,指令流会回到出现错误的那条指令持续执行,典型的例子是页面错误,中断处理程序会将错误的页面找到并调入系统,然后再执行错误指令即可;

对于异常,处理器也期待可以恢复,故会发挥到下一条指令,典型的例子是调试断点;

至于终止,处理器已经不期待指令流可以执行了,所以指令流不会再回去执行了。

中断和异常不一样的是,中断是异步的,所以当中断会被分为上半部分和下半部分(这个说法是Linux的,但是这个说法很好的诠释了中断处理的本质,上半部分用于处理最紧急的事件,下半部分则处理不那么紧急的事件),上半部分执行完后,代码流可能会返回之前的指令流,此时中断处理可能还没完成,直到下半部分处理完,中断才算完成,不过此时之前的指令流可能已经执行完了,故中断可以是异步的,就是源自于此。

比如说,在上面的USB总线的中断到来时候,windows正在执行某个线程,此时如果处理器可以响应这个USB中断,那么它会将当前线程压入堆栈,然后控制权交给中断服务例程,中断服务例程则会处理最紧急的部分,例如说将总线上的数据取下,然后中断服务例程会插入一个DPC/APC/工作项,将中断的下半部分一些不重要的事情会放在这些处理方式中里面执行,指令流再返回之前的指令流,或者不返回接着执行DPC也是可能的。

中断的异步性是通过DPC/APC/工作项来体现的,总线驱动的中断处理例程往往只会处理非常短的时间,它可能仅仅将数据拷贝一下或者设置一下,然后就马上返回了;处理器不应该在高级别的IRQL下运行太久的时间,这会导致性能急剧下降,对其他中断的响应速度下降。

中断服务例程

生成中断的设备驱动程序必须至少有一个中断服务例程 (ISR) 。ISP例程必须执行适用于设备的任何操作来消除中断,可能包括阻止设备中断;它应仅执行保存状态并将DPC 排队的必要操作,以低于执行ISP例程的优先级(IRQL)完成I/O操作。

驱动程序的ISP例程在中断上下文中执行,由 IoConnectInterruptEx 的 SynchronizeIrql 参数指定为某个系统分配的 DIRQL。

ISP例程是可中断的,具有更高系统分配DIRQL的另一个设备可以随时中断或高IRQL系统中断。

在系统调用ISP例程之前,它会获取中断的自旋锁,因此ISP例程不能在另一个处理器上同时执行。ISP例程返回后,系统会释放旋转锁。

由于ISP例程以相对较高的IRQL运行,因此它使用当前处理器上的等效或更低IRQL屏蔽中断,因此它应尽快返回控制权。 此外,在DIRQL 上运行ISP例程会限制ISP例程可以调用的支持例程集。 

通常,ISP例程执行以下常规步骤:

如果导致中断的设备不受ISP例程支持,则ISP例程将立即返回 FALSE。

否则,ISP例程会根据需要清除中断,保存所需的任何设备上下文,并将DPC 排队以在较低的IRQL处完成I/O操作。然后,ISP例程必须返回 TRUE。

具体而言,在不涉及重叠设备I/O操作的驱动程序中,ISP例程应执行以下操作:

1. 确定中断是否为虚假中断。 如果是,请立即返回 FALSE ,以便立即调用中断设备的ISP例程。 否则,请继续中断处理。

2. 如有必要,请停止设备中断。

3. 收集DPCForISP例程(或 CustomDpc) 例程完成当前操作的I/O处理所需的任何上下文信息。

4. 将此上下文存储在DpcForISP例程或CustomDpc例程可访问的区域中,通常存储在处理当前I/O请求导致中断的目标设备对象的设备扩展中。

如果驱动程序与I/O操作重叠,则上下文信息必须包括DPC 例程需要完成的未完成请求计数,以及DPC 例程完成每个请求所需的任何上下文。 如果在DPC 运行之前调用ISP例程来处理另一个中断,则它不得覆盖DPC 尚未完成的请求的已保存上下文。

5. 如果驱动程序具有DPCForISP例程例程,请使用指向当前 IRP、目标设备对象和已保存上下文的指针调用 IoRequestDpc 。 IoRequestDpc 会将DPCForISP例程例程排入队列,只要IRQL低于处理器上的DISPATCH_LEVEL即可运行。

如果驱动程序具有CustomDpc例程,请使用指向与CustomDpc 例程关联的DPC 对象的指针 (调用 KeInsertQueueDpc) 指向CustomDpc例程完成操作所需的任何已保存上下文的指针。

通常,ISP例程还会传递指向当前 IRP 和目标设备对象的指针。 只要IRQL低于处理器上的DISPATCH_LEVEL, 就会运行CustomDpc例程。

6. 返回 TRUE 以指示其设备生成了中断。

通常,ISP例程不会执行实际I/O处理来满足 IRP。 相反,它会停止设备中断,设置必要的状态信息,并将驱动程序的DPCForISP例程或CustomDpc排队,以执行任何必要的I/O处理来满足导致设备中断的当前请求后返回。

ISP例程必须在尽可能短的时间间隔内以DIRQL运行。 遵循此准则会增加计算机中每台设备的I/O吞吐量,因为以DIRQL运行会屏蔽系统为其分配了较小或相等IRQL值的所有中断。

 

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

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

相关文章

C语言:指针详解(3)

目录 一、字符指针 二、数组指针 1.数组指针的定义 2.数组指针的初始化 3. 二维数组传参的本质 三、函数指针 1.函数指针的创建 2.函数指针的使用 3.有趣的代码(1) 4.有趣的代码(2) 四、typedef关键字 1.typedef的使用方法 2.typedef和#define的区别 五、函数指针…

前端性能优化知识梳理

1.重要性 当我们面试的时候,前端性能优化方面算是必考的知识点,但是工作中我们又很少会重点的对项目进行前端优化,它真的不重要吗? 如果我们可以将后端响应时间缩短一半,整体响应时间只能减少5%~10%。而如果关注前端…

imx6ull启动方式和镜像文件烧写

文章目录 前言一、BOOT启动方式1.串行下载2.内部BOOT模式 二、内部BOOT模式详细流程1.启动设备的选择2.镜像烧写 总结 前言 💦 I.MX6Ull 支持多种启动方式以及启动设备,比如可以从 SD/EMMC、NAND Flash、QSPI Flash等启动。用户可以根据实际情况&#x…

【web安全】-- 命令执行漏洞详解

本文将从原理开始介绍命令执行漏洞并附有三个实例来供各位客官学习 文章目录 一、什么是命令执行漏洞二、出现的原因三、有可能存在命令执行漏洞的函数(php)1、利用一些函数来实现命令执行2、直接执行系统命令的函数 四、命令拼接符号1、Windows2、linux…

QT:不同UI间数据,信号的交互

前言 接上文,手动绘制的矩形框毕竟还是在上位机的播放界面内,想要把数据发送给3559还是需要通过串口或者网口发送,没有部署在一个界面就需要不同UI间数据和信号进行交互了,数据还好说,全局变量都可以做到,信…

【c++】反向迭代器的探究实现

🔥个人主页:Quitecoder 🔥专栏:c笔记仓 在list中我们实现了正向的迭代器,学习完优先级队列后,我们也对适配器模式有了一个深刻的理解,这篇文章基于这种模式下,实现各类容器的反向迭…

Docker-compose部署LTC同步节点

1、下载ltc程序包,litecoin下载地址 下载页 mkdir /data/docker-compose/ltc cd /data/docker-compose/ltc https://github.com/litecoin-project/litecoin/releases/download/v0.21.3/litecoin-0.21.3-x86_64-linux-gnu.tar.gz2、编写dockerfile和bitcoin.conf b…

我开始接单/兼职/搞副业/建设个人社区,为自己谋后路了。

我开始接单/兼职/搞副业/建设个人社区,为自己谋后路了。 简述 大家好,我是小荣,一个前端开发程序员。我最近开始在业余时间接私单了,也在想一些能够带来成长,收入的副业,主要也是为了自己谋后路&#xff…

C语言:数据结构(双向链表)

目录 1、双向链表的结构2、顺序表和双向链表的优缺点分析3、双向链表的实现 1、双向链表的结构 注意:这⾥的“带头“跟前面我们说的“头节点”是两个概念,实际前面的在单链表阶段称呼不严谨,但是为了更好的理解就直接称为单链表的头节点。 带…

SSH远程登录实操实验!

ssh远程登录协议:默认端口号22 以下实验7-2是服务端,7-1是客户端 服务器的相关信息: 服务名称:sshd 服务端主程序:/usr/sbin/sshd 服务端配置文件:/etc/ssh/sshd_config 客户端相关信息: …

python的输入输出(爽文,备忘,查询,友好)

Python中的输入输出主要涉及到输入函数和输出函数。 输出函数:print() print() 函数用于将信息输出到屏幕上。它可以输出字符串、变量的值,以及其他各种数据类型。 name "Alice" age 30 print("姓名:", name, "年龄:&quo…

ip ssl证书无限端口网站

IP SSL证书是由CA认证机构颁发的一种特殊数字证书。大部分SSL数字证书都需要用户使用域名进行申请,想要对公网IP地址加密实现https访问就需要申请IP SSL证书。IP SSL证书采用了强大的加密算法,可以有效地防止数据在传输过程中被窃取或篡改,具…

[C语言]典型例题:小蚂蚁爬橡皮筋、买汽水问题、导致单词块、菱形打印……

1、小蚂蚁爬橡皮筋问题 假设橡皮筋长4m,小蚂蚁从一端爬向另一端每天爬1m,且每爬了1m,橡皮筋会立马拉伸4m,在理想条件下,小蚂蚁需要爬多少天可以到达橡皮筋的另一端? 不仔细想,我们很可能认为小蚂…

Scikit-Learn回归树

Scikit-Learn回归树 1、决策树1.1、什么是决策树1.2、决策树学习的步骤1.3、决策树算法 1、决策树 决策树(DTs)是一种用于回归和分类的有监督学习方法。通常,决策树用于分类问题;当决策树用于回归问题时,称为回归树。回…

【C++】:日期类的实现 -- 日期计算器

前言 1.日期类是一种十分经典的类型。对于C的初学者,它能够帮助我们融会贯通许多C的基础知识,它涉及许多的基础语法,比如引用,函数重载,传值/传参返回,构造函数,运算符重载,const成…

【Python小练】求斐波那契数列第n个数

题目 输出斐波那契数列第n个数。 分析 首先我们要知道,斐波那契数列,这个数列从第三位开始等于前两个数的和,要知道数列第n个数(n>2),就要知道其前两相的值,着就需要用到递归了。来看一下吧…

C语言实验-循环结构和选择结构

一&#xff1a; 求和:1(14)(149)(14916)…(14916…n2)? 其中n的值由键盘输入&#xff1b; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h>int main() {int sum 0;int n 0;printf("请输入一个整数");scanf("%d", &n);for (int i 0; i &l…

Apache中如何配置 ws 接口

Apache中如何配置 wss 接口 在Apache中配置WebSockets的支持&#xff0c;你需要使用mod_proxy_wstunnel模块&#xff0c;该模块是Apache的一个代理模块&#xff0c;它允许你代理WebSocket请求。 以下是配置步骤的简要说明和示例&#xff1a; 确保你的Apache服务器安装了mod_…

【最大公约数 排序】2344. 使数组可以被整除的最少删除次数

本文涉及知识点 最大公约数 排序 LeetCode2344. 使数组可以被整除的最少删除次数 给你两个正整数数组 nums 和 numsDivide 。你可以从 nums 中删除任意数目的元素。 请你返回使 nums 中 最小 元素可以整除 numsDivide 中所有元素的 最少 删除次数。如果无法得到这样的元素&a…

【高质量】2024五一数学建模C题保奖思路+代码(后续会更新)

你的点赞收藏是我后续更新的最大动力&#xff01; 一定要点击文末的卡片&#xff0c;那是获取资料的入口&#xff01; 你是否在寻找数学建模比赛的突破点&#xff1f; 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024 年五一数学建模&#xff08;C题&#xff09;…