Linuxer.
全部博文(199)
分类: LINUX
2013-09-17 08:59:13
原文地址:linux的中断和异常(一) 作者:zhangyd6
一 异常和中断
同步:指令执行时cpu控制单元产生的,说他是同步是因为只有指令终止后cpu才发生中断;
异步:其他硬件设备依照cpu时钟产生的。所以,同步和异步中断分别称为异常和中断。
中断 :可屏蔽中断(Maskeble interrupt) 可屏蔽的和非屏蔽的
异常 :故障(Fault) 如 缺页异常处理程序
陷阱(Trap) 当执行没有必要重新执行已终止的指令时,出发陷阱。
异常终止(Abort) 用于报告严重的错误。
编程异常 (Programmed exception)在编程者发出请求是发生。是由int 或(int3)指令时触
高级可编程中断控制器(Advanced Programmable Interrupt Controller APIC )
二 中断和异常处理程序的嵌套执行
中断处理程序从不执行可以导致缺页的异常的操作,一个中断处理程序可以抢占其他的中断处理程序,也可以抢占异常处理程序。异常处理程序从不抢占中断处理程序。为防止用户进程试图发生一个中断信号,可以通过把中断门后陷阱们描述符的DPL 字段设置成0来实现。如果进程试图发出其中的一个中断信号,使DPL 和CPL的值有冲突,产生一个“通用保护”异常。少数情况下,用户进程必须发出一个编程异常 只要把中断或陷阱门描述符的DPL设为3。
三 陷阱门和中断门
1 中断门
2 系统门 用户态的进程可以访问的一个intel陷阱门。通过系统门来激活四个linux的异常处理程序,向量
3 4 5 及128,
3 陷阱门 用户态的进程不能访问的一个intel陷阱门。
set_intr_gate(n, addr); set_system__gate(n,addr); set_trap_gate(n, addr); 以上三组函数用来在IDT中插入门。
四 IDT的初步初始化
setup_idt();汇编语言函数用同一个中断门(即指向ignore_int()的中断处理程序)来填充256个idt_table表项:ignore_int()从不被执行,在控制台或日志文件中出现“Unknown interrupt”的消息来标志出现一个硬件的问题,或者是一个内核的问题(一个中断或异常未被适当处理)。
五 异常处理
在两种情况下,linux利用CPU异常更有效的管理硬件资源。
第一,“保存FPU, MMX ,XMM寄存器” 中浮点协处理器。“设备不可用异常”与cr0寄存器的TS标志一起用来把新值装入浮点寄存器。
第二, 缺页情况。
六 异常或中断的处理过程
1 保存寄存器的值
2 进入和离开异常处理程序,执行异常处理程序的C函数名总是由do_前缀和处理程序名组成。其中大部分函数把硬件出错码和异常向量保存在当前进程的描述符中,然后,向当前进程发送一个适当的信号。异常处理程序终止后,当前进程就关注这个信号。该信号要么由进程自己的信号处理程序来处理,要么由内核来处理。在后中情况下内核一般会杀死这个进程。
3 中断有三种类型 I/O中断 时钟中断 和 处理器间的中断
I/O 中断处理
中断处理程序可以分为
IRQ共享
IRQ 动态分配: 中断处理程序是代表进程执行的,他所代表的进程总是处在TASK_RUNNING 状 态,不能出现僵死状态。
linux把紧随中断要执行的操作分为三类:
紧急的: 必须在禁止可屏蔽中断的情况下。
非紧急的: 必须在开中断的情况下。
非紧急可延迟的:
所有I/O 中断处理程序必须执行四个形同的基本步骤
1 砸内核态堆栈中保存IRQ 的值和寄存其的的内容。
2 为正在给IRQ线服务的PIC发送一个应答,这将允许PIC进一步发出中断。
3 执行共享这个IRQ的所有设备的中断服务例程
4 跳到 ret_from_intr()的地址后终止。
七 中断向量
0~19 (0x0~0x13) 非屏蔽中断和向量
20~31 (OX14~0X
32~127 (0x20~0x
128 (0x80) 系统调用
129~238(0x81=0xee) 外部中断(IRQ)
239 (0XEF) 本地APIC时钟中断
240-250(0xf0~0xfa) 由linux留做将来使用
251~255(0xfb~0xff) 处理器间中断
为IRQ可配置设备选择一条线有三种方式
1 设置一次些硬件跳线
2 安装设置是执行一个实用程序
3 在系统启动时执行一个硬件协议
八 IRQ 的数据结构
hw_irq_controller(); 驱动程序可见的中断源透明的链接到适当的控制器。
九 IRQ 在多处理器系统的分发
在系统启动的过成中,引导cpu执行setup_IO_APIC_irqs()函数以初始化I/O APIC芯片。在系统启动期间,所有的cpu都执行setup_local_APIC()函数,该函数处理本地的APIC初始化。特别是 每个芯片的任务优先级寄存器(TPR)都初始化为一个固定值。