您的位置:首页 > 其它

x86保护模式的几点思考——IRQ、中断号和中断向量

2011-05-02 13:53 288 查看
说到中断号和中断向量,也许你并不陌生,这两个概念也可以将中断原理解释个大概了。但是当你深究下去的时候你会碰到另一个东西——IRQ,之后自然而然的对从硬件级开始到中断向量表的整个中断过程产生好奇,然后继续研究,就能学到下文中所包含的内容了。

你没有硬件基础?我也没有!所以让咱们从零开始。

IRQ(Interrupt ReQuest),中文翻译应该为“中断请求”,但实际上一些文档中说到IRQ时一般就是指“中断请求信号线”——8259A的一个引脚,一个8259A有8个这样的引脚IRQ0~IRQ7。那8259A又是什么?好问题!想到问题后咱们就来解决它,其实咱们这此普通人跟牛人的区别就在这儿。

IRQ、中断号与8259A

我们都知道计算机可以挂接上许多外部设备,比如键盘、磁盘驱动器、鼠标、声卡……等等一系列设备,而这些设备都可能在同一时刻向CPU发出中断信号(也就是外部中断),那么CPU到底应当响应哪一个设备的中断信号呢?这都通过另外一个芯片来控制,在IBM PC机中,这个芯片常常被称作:可编程中断控制器(PIC)8259A,说它可编程,是因为我们可以通过编程来改变它的功能。比如我可以通过编程设定CPU应当优先响应哪一个中断,屏蔽哪些中断等等一系列事件。它的结构图如下。



从图中可以看到,一个8259A芯片的组成可以分为5个主要的逻辑控件:中断屏蔽寄存器(IMR)、中断请求寄存器(IRR)、优先级仲裁单元(Prioriry Resolver)、中断向量寄存器(ISR)和控制逻辑单元(Control Logic)。一个8259A芯片有IRQ0~IRQ7七个IRQ引脚,一个IRQ对应着一个中断号,一个中断号对应着一个中断向量,一个中断向量对应着一个中断处理子程序(ISR,注意这个ISR是Interrupt Service Routine的缩写)。

也许你已经对硬件级的中断处理过程猜到个大概了,当一个IRQ接收到一个外部中断信号后处理的流程应该是以下几个步骤:

1.IMR判断该中断是否被屏蔽掉(IMR中相应的位置1)了,如果被屏蔽掉了结束处理,否则跳转到第2步;

2.将收到的中断请求保存到IRR中(IRR中相应的位置1,IRR相当于一个缓存,用来保存等待CPU处理的中断信号),等待CPU当前指令执行结束后向8259A发送INTA信号,表示现在CPU可以处理中断请求了,此时IRR相应位被reset,然后跳转到第3步;

3.PR根据等待处理的中断信号对应的IRQ,选择最高优先级的中断信号进行处理,IRQ0优先级最高,接着是IRQ1、IRQ2……然后跳转到第4步;

4.CPU向8259A发送INTA信号,要求被告知IRQ对应的中断号,然后根据中断号到IDT中找到相应的中断向量,跳转到对应的中断处理子程序(中断向量和中断处理了程序是什么?后面会说到,这里你只把它们当成是一个函数调用就可以了)入口地址开始执行,此时中断号对应的ISR中位被set(IRR被reset和ISR被set的过程是对应的),如果此时有更高优先级的中断信号等待处理,跳转到第3步。

值得注意的是,第2步中有个细节“等待CPU当前指令执行结束后……”,往常我们理解的中断是,当CPU接收到一个中断信号时会立即响应。其实不完全是这样的,CPU需要将当前正在执行的指令执行完毕才会响应中断。

罗罗嗦嗦到现在,IRQ跟中断号到底有什么区别啊?你能想到这个问题说明你的思考过程还没跑题,比我强多了!一般我看东西时,看着看着就把初衷给忘了……

如果IRQ还算能好理解点,那么中断号就稍稍抽象一点,中断号是可编程的,也就是说一个IRQ对应着哪个中断号由咱们程序员说得算(一种God的感觉油然而生)。默认情况下,IRQ对应的中断号是由BIOS初始化的,IRQ0~IRQ7对应着中断号0x8~0xF。而可编程表现在,我们可以将IRQ0对应的中断号修改成0~255中的任意一个数,我们设为INT_NUM,然后IRQ1~IRQ7对应的中断号就跟着变成INT_NUM+1~INT_NUM+7了。举个例子,我们将IRQ0对应的中断号改到0x10,那么IRQ1对应的中断号就是0x11、IRQ2的是0x12……IR7的是0x17。

说到这里,你应该明白了IRQ和中断号是个什么,以及它们之关的关系了。然后你又有问题了,我们可以设置IRQ对应的中断号,but how?你爷爷的,又跟我想一块儿去了,咱俩可以去拜把子了!

既然8295A是个芯片,那么自然需要程序员来做一起配置的工作,当然修改IRQ对应的中断号也算一种配置了!对8259A的编程是通过向其相应的端口发送一系列的ICW(初始化命令字)完成的。总共需要发送四个ICW,它们都分别有自己独特的格式,而且必须按次序发送,并且必须发送到相应的端口,主片的端口号为0x20,从片的端口号为0xA0。那么从片又是啥?咋这么多不懂的呢,唉……

从片是个啥?怎么设置IRQ与中断号的对应关系?

一个8259A芯片的可以接最多8个中断源,但由于可以将2个或多个8259A芯片级连(cascade),并且最多可以级连到9个,所以最多可以接64个中断源。早期,IBM PC/XT只有1个8259A,. 但设计师们马上意识到这是不够的,于是到了IBM PC/AT,8259A被增加到2个以适应更多外部设备的需要,其中一个被称作Master,另外一个被称作Slave,Slave以级连的方式连接在Master上。如今绝大多数的PC都拥有两个8259A,这样最多可以接收15个中断源。两个8259A芯片级连如下图所示。





从片弄明白了,IBM的工程师原来也是有时代局限性的,不会用发展的眼光看问题啊……言归正传,上面说了我们可以通过4个ICW1~ICW4可配置8259A,IRQ与中断号的对应就是通过ICW2(一个8位的数)来完成的。

ICW2:发送到0x21(主片)及0xA1(从片)端口

7 6 5 4 3 2 1 0
A7A6A5A4A3000
ICW2用来指示出IRQ0使用的中断号是什么,因为最后三位均是零,因此要求IRQ0的中断号必须是8的倍数,这又是一个很巧妙的设计。因为IRQ1的中断号就是IRQ0的中断号+1,IRQ2的中断号就是IRQ0的中断号+2,……,IRQ7的中断号就是IRQ0的中断号+7,刚好填满一个8个的中断向量号空间。

到这里,基本弄明白中断硬件级的原理了,至于其他的三个ICW,各位看官可以参考张昆藏的《IBM PC/XT微型计算机接口技术》,不错的一本书。

最后一个问题了,中断向量是个什么东西?

我所理解的中断向量

中断向量实际上就是中断号,一般是可以这么理解的,但是按我的习惯(请允许我修改下概念),我把中断向量理解为中断号与中断服务子程序的一个映射,如果用y表示中断服务子程序、x表示中断号,那么y=f(x)中的运算法则f就是中断向量了。中断向量实际上就是一个程序入口,很多时候中断向量就是一个jmp指令(看官可以思考一下,这里为什么不用call),例如jmp isrClock,跳转到相应的中断处理子程序(例子里的isrClock);而中断向量表就是所有中断向量组成的一张表,对应到代码就是N个jmp指令。当CPU根据IRQ获得中断号的时候,就会计算“中断向量表的起始地址+中断号”得到相应的中断向量,然后进行跳转。

好了,说到这里各位看官也许已经看烦了,其实学习的过程是很枯燥的,但是成功的人会很享受这种枯燥,这也是我们差的那一步!

一句话,学习的过程中应该能够“耐得住寂寞,经得起诱惑……”

注:以下源自张昆藏的《IBM PC/XT微型计算机接口技术》,讲了下模块设计规则,大家可以看下。他就把中断号和中断向量理解为一个概念,很多书中也都是这么讲的,千万不要因为我的理解而出现混淆。

这里出现了一个中断向量的概念,其实它就是一个被送往CPU数据线的一个整数。CPU给每个IRQ分配了一个类型号,通过这个整数,CPU来识别不同类型的中断。这里可能很多朋友会寻问为什么还要弄个中断向量这么麻烦的东东?为什么不直接用IRQ0~IRQ15就完了?比如就让IRQ0为0,IRQ1为1……,这不是要简单的多么?其实这里体现了模块化设计规则以及节约规则。

首先我们先谈谈节约规则,所谓节约规则就是所使用的信号线数越少越好,这样如果每个IRQ都独立使用一根数据线,如IRQ0用0号线,IRQ1用1号线……这样,16个IRQ就会用16根线,这显然是一种浪费。那么也许马上就有朋友会说:那么只用4根线不就行了吗(24=16)?

对于这个问题,则体现了模块设计规则。我们在前面就说过中断有很多类,可能是外部硬件触发,也可能是由软件触发,然而对于CPU来说中断就是中断,只有一种,CPU不用管它到底是由外部硬件触发的还是由运行的软件本身触发的,因为对于CPU来说,中断处理的过程都是一样的:中断现行程序,转到中断服务程序处执行,回到被中断的程序继续执行。CPU总共可以处理256种中断,而并不知道,也不应当让CPU知道这是硬件来的中断还是软件来的中断,这样,就可以使CPU的设计独立于中断控制器的设计,因为CPU所需完成的工作就很单纯了。CPU对于其它的模块只提供了一种接口,这就是256个中断处理向量,也称为中断号。由这些中断控制器自行去使用这256个中断号中的一个与CPU进行交互。比如,硬件中断可以使用前128个号,软件中断使用后128个号,也可以软件中断使用前128个号,硬件中断使用后128个号,这于CPU完全无关了,当你需要处理的时候,只需告诉CPU你用的是哪个中断号就行,而不需告诉CPU你是来自哪儿的中断。这样也方便了以后的扩充,比如现在机器里又加了一片8259芯片,那么这个芯片就可以使用空闲的中断号,看哪一个空闲就使用哪一个,而不是必须要使用第0号,或第1号中断。其实这相当于一种映射机制,把IRQ信号映射到不同的中断号上,IRQ的排列或说编号是固定的,但通过改变映射机制,就可以让IRQ映射到不同的中断号,也可以说调用不同的中断服务程序,因为中断号是与中断服务程序一一对应的,这一点我们将在随后的内容中详细描述。8259A将中断号通知CPU后,它的任务就完成了,至于CPU使用此中断号去调用什么程序它就不管了。
本文出自 “New World” 博客,请务必保留此出处http://snower.blog.51cto.com/2918921/557678
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: