- 1、本文档共35页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
深入理解Linux内核中断
深入理解Linux 内核中断
一直认为,理解中断是理解内核的开始。中断已经远远超过仅仅
为外围设备服务的范畴,它是现代体系结构的重要组成部分。
1、 基本输入输出方式
现代体系结构的基本输入输出方式有三种:
(1) 程序查询:
CPU 周期性询问外部设备是否准备就绪。该方式的明显的缺点
就是浪费CPU 资源,效率低下。
但是,不要轻易的就认为该方式是一种不好的方式,通常效率低
下是由于CPU 在大部分时间没事可做造成的,这种轮询方式自有应
用它的地方。例如,在网络驱动中,通常接口(Interface)每接收一
个报文,就发出一个中断。而对于高速网络,每秒就能接收几千个报
文,在这样的负载下,系统性能会受到极大的损害。
为了提高系统性能,内核开发者已经为网络子系统开发了一种可
选的基于查询的接口NAPI(代表new API)。当系统拥有一个高流量
的高速接口时,系统通常会收集足够多的报文,而不是马上中断CPU。
(2)中断方式
这是现代CPU 最常用的与外围设备通信方式。相对于轮询,该
方式不用浪费稀缺的CPU 资源,所以高效而灵活。中断处理方式的
缺点是每传送一个字符都要进行中断,启动中断控制器,还要保留和
恢复现场以便能继续原程序的执行,花费的工作量很大,这样如果需
要大量数据交换,系统的性能会很低。
(3)DMA 方式
通常用于高速设备,设备请求直接访问内存,不用CPU 干涉。
但是这种方式需要DMA 控制器,增加了硬件成本。在进行DMA 数
据传送之前,DMA 控制器会向CPU 申请总线控制 权,CPU 如果允
许,则将控制权交出,因此,在数据交换时,总线控制权由DMA 控
制器掌握,在传输结束后,DMA 控制器将总线控制权交还给CPU。
2、中断概述
2.1、中断向量
X86 支持256 个中断向量,依次编号为0~255。它们分为两
类:
(1)异常,由CPU 内部引起的,所以也叫同步中断,不能被CPU
屏蔽;它又分为Faults(可更正异常,恢复后重新执行),Traps(返
回后执行发生trap 指令的后一条指令)和Aborts(无法恢复,系统只
能停机);
(2)中断,由外部设备引起的。它又分为可屏蔽中断(INTR)和非
可屏蔽中断(NMI)。
Linux 对256 个中断向量分配如下:
(1)0~31 为异常和非屏蔽中断,它实际上被Intel 保留。
(2)32~47 为可屏蔽中断。
(3)余下的48~255 用来标识软中断;Linux 只用了其中一个,
即128(0x80),用来实现系统调用。当用户程序执行一条int 0x80
时,就会陷入内核态,并执行内核函数system_call(),该函数与具
体的架构相关。
2.2、可屏蔽中断
X86 通过两个级连的8259A 中断控制器芯片来管理15 个外部
中断源,如图所示:
外部设备要使用中断线,首先要申请中断号(IRQ),每条中断线
的中断号IRQn 对应的中断向量为n+32,IRQ 和向量之间的映射可
以通过中断控制器商端口来修改。X86 下8259A 的初始化工作及
IRQ 与向量的映射是在函数init_8259A()(位于
arch/i386/kernel/i8259.c)完成的。
CPU 通过INTR 引脚来接收8259A 发出的中断请求,而且CPU
可以通过清除EFLAG 的中断标志位(IF)来屏蔽外部中断。当IF=0
时,禁止任何外部I/O 请求,即关中断(对应指令cli)。另外,中断
控制器有一个8 位的中断屏蔽寄存器(IMR),每位对应8259A 中的
一条中断线,如果要禁用某条中断线,相应的位置 1 即可,要启用,
则置0。
IF 标志位可以使用指令STI 和CLI 来设置或清除。并且只有当
程序的CPL=IOPL 时才可执行这两条指令,否则将引起一般保护
性异常(通常来说,in,ins,out,outs,cli,sti 只有在CPL=IOPL
时才能执行,这些指令称为I/O 敏感指令)。
以下一些操作也会影响IF 标志位:
(1)PUSHF 指令将EFLAGS 内容存入堆栈,且可以在那里修改。
POPF 可将已经修改过的内容写入EFLAGS 寄存器。
(2)任务切换和IRET 指令会加载EFLAGS 寄存器。因此,可修
改IF 标志。
(3)通
文档评论(0)