一.中断处理
1.1.中断概述
所谓中断是指CPU在执行程序的过程中,出现了某些突发事件急待处理,CPU必须暂停执行当前的程序,转去执行处理突发事件,处理完毕后CPU又回原程序被中断的位置并继续执行。
根据中断的来源,中断可分为内部中断和外部中断,内部中断的中断源来自CPU内部(软件中断指令,溢出,除法错误等),外部中断的中断源来自CPU的外部,由外设提出。
1.2.linux中断处理程序架构
设备的中断会打断内核中进程的正常调度和运行,系统对更高吞吐率的追求势必要求中断服务程序尽可能的短小精悍。但是,这个良好的愿望往往与现实并不吻合。在大多数真实的系统中,当中断到来时,要完成的工作往往并不会是短小的,它可能要进行较大的耗时处理。
1.2.1.linux中断处理机制
图1 描述了linux内核的中断处理机制
为了中断执行了时间尽可能短和中断处理需完成大量工作之间找到一个平衡点,linux将中断处理程序分解为两个部分:顶半部(top half)和底半部(bottom half).
1.2.1.1.顶半部
顶半部完成尽可能少的比较紧急的功能,它往往只是简单地读取寄存器中的中断状态并清除中断标志后就进行”登记中断”的工作。”登记中断”意味着将底半部处理程序挂到该设备的底半部执行队列中去。这样顶半部执行的速度就会很快,可以服务更多的中断请求。
1.2.1.2.底半部
底半部几乎完做了中断处理程序所有的事件,而且可以被新的中断打断,这也是底半部和顶半部的最大不同,因为顶半部往往设计成不可中断。底半部则相对来说并不是非常紧急的,而相对比较耗时,不在硬件中断服务程序中执行。
1.3.中断软件设计流程
图2为中断处理流程
图2 中断软件设计处理流程
1.4.软件设计需要使用到的API函数
1.4.1.中断注册
int request_irq(unsigned int irq,void (*handler)(int, void *,struct pt_regs *),unsigned long flags,const char *devname,void *dev_id)
unsigned int irq //中断号
void (*handler)(int, void *,struct pt_regs *)//中断处理函数
unsigned long flags //与中断管理有关的各种选项
const char *devname//设备名
void *dev_id //共享中断时使用
1.4.1.1.中断标志
.IRQF_DISABLED(SA_INTERRUPT)
如果设置该位,表示是一个”快速”中断处理程序;如果没有设置这位,那么是一个”慢速”中断处理程序。
IRQF_SHEARED(SA_SHIRD)
该位表明中断可以在设备间共享。
1.4.2.中断处理函数流程
1)判断是否是本设备产生了中断(一般用于共享中断)
2)清除中断位(如果设备支持自动清除,则不需要这步)
3)中断处理,通常是数据接收。
4)唤醒等待数据的进程。
1.4.2.1.中断处理函数注意事项
1).不能向用户空间发送或者接受数据
2).不能使用可能引起阻塞的函数
3).不能使用可能引起调度的函数
1.4.3.使能和屏蔽中断
void disable_irq(int irq);
void disable_irq_nosync(int irq);
void enable_irq(int irq);
disable_irq_nosync()与disable_irq()的区别在于前者立即返回,而后者等待目前的中断处理完成。由于disable_irq()会等待指定的中断被处理完,因此如果在n号中断的顶半部调用disable_irq(n),会引起系统的死锁,这种情况下,只能调用disable_irq_ nosync.
1.4.4.释放中断
void free_irq(unsigned int irq,void *dev_id)
阅读(1164) | 评论(0) | 转发(0) |