分类: 嵌入式
2016-04-13 18:53:26
linux内核的中断机制是一个非常重要的知识点,本文将针对该知识点做一个详细的介绍,分析:一、为什么要有中断;二、中断的硬件触发和连接;三、中断的处理流程;四、中断的软件编程;五、linux内核中断编程;六、linux内核对于中断的要求; 七、linux内核提出的顶半部和底半部机制;八、底半部机制之tasklet;九、底半部机制之工作队列;十、底半部机制之软中断这十个方面。并给出参考代码。
一、为什么要有中断
外设的处理速度远远慢于CPU的处理速度
如果采用轮询方式(CPU一直等待)处理外设,会降低CPU的利用率
如果采用中断方式处理外设,会大大提高CPU的利用率
以cpu读取串口信息为例:
为了防止串口数据的丢失,不采用中断,采用轮询,CPU只能不停读取串口的信息:
如果采用中断,cpu当发现串口数据不可读时,cpu可以做其他事情,一旦串口数据准备就绪,串口会给CPU发送一个中断信号,告诉cpu,数据准备就绪,请来处理,cpu处理完毕以后,再接着执行原先被打断的任务!
二、中断的硬件触发和连接
外设的中断信号并不是直接输送给CPU,而是先给中断控制器,经过中断控制器的判断以后,再决定是否给CPU发送中断信号。
中断控制器的作用:
1.能够屏蔽或者使能某个中断信号
2.能够设置中断优先级
3.能够设置外设中断信号的有效触发方式
4.如果是多核,能够指定中断信号给哪个CPU发送
一旦CPU接收到了外设的中断信号之后,CPU开始进行中断处理
三、中断的处理流程
四、中断的软件编程
不管是裸板还是带操作系统,中断的编程步骤一致:
1. 编写异常向量表的代码
2. 编写保护现场的代码
3. 编写中断处理函数
4. 编写恢复现场的代码
不管是在裸板上(keil)还是在linux内核中,进行中断编程,1,2,4三步骤已经有内核实现,驱动开发者只需要向内核注册中断处理函数即可!
五、linux内核中断编程
内核中断编程,只需将中断处理函数注册到内核中即可,一旦中断触发,内核执行对应的中断处理函数!
向内核注册和卸载中断处理函数的方法为:
request_irq/free_irq
函数原型:
request_irq(unsigned int irq,
irq_handler_t handler,
unsigned long flags,
const char* name,
void *dev)
函数功能:
1.向内核申请硬件中断资源
2.然后注册硬件中断的中断处理函数到内核
参数:
irq: 硬件中断对应的软件编号,又称中断号(类似于硬件中断的身份证
号),从32开始,0~31内核保留!中断号由芯片厂家在内核源
码定义!
例如:
第一个硬件中断XEINT0,对应的软件编号为IRQ_EINT(0);
第十个硬件中断XEINT10,对应的软件编号为IRQ_EINT(10);
在//arch/arm/mach-s5pv210/include/mach/irqs.h中
handler: 中断处理函数
flags: 中断处理标志,flags要指定有效的中断触发方式
IRQF_TRIGGER_FALLING
IRQF_TRIGGER_RISING
IRQF_TRIGGER_HIGH
IRQF_TRIGGER_LOW
可以做位或运算
对于内部中断,flags给0
name: 中断名称,将来出现在cat /proc/interrupts
dev: 给中断处理函数传递参数,不传递给NULL
中断处理函数说明:
原型:typedef irqreturn_t (* irq_handler_t)(int, void *);
返回值类型定义:typedef enum irqreturn irqreturn_t;
释放中断资源和删除中断处理函数
void free_irq(int irq,void *dev)
irq:释放中断号资源
dev:给中断处理函数传递的参数,切记一定要和注册是传递的参数一样
六、linux内核对于中断的要求
内核要求中断处理函数执行的速度要快,不能做休眠操作以避免中断长时间占用CPU资源,导致系统的并发和响应能力受到影响
在linux内核,“任务”包括进程,硬件中断,软中断
优先级的划分如下:
硬件中断>软件中断>进程
硬件中断无优先级
软中断、进程有优先级
在linux内核中,中断不隶属于任何进程,不参与进程的调度
七、 linux内核对于以上问题提出了顶半部和底半部机制加以优化
采用顶半部和底半部机制的特点是:
(1)避免中断长时间占用CPU资源,导致系统的并发和响应能力受到影响
(2)让cpu的资源能够在多个任务中共享
顶半部的特点:
1.本质还是中断处理函数
2.执行原先中断函数中紧急,耗时短的任务
3.不可被中断
4.登记底半部的内容,以便将来CPU去执行
底半部的特点:
1.本质就是延后执行的一种手段,不一定非要和顶半部配合使用
例如将来让某个事情延后执行,可以单独采用底半部机制
2.如果有中断,执行原先中断处理函数中不紧急,耗时较长的任务
3.可被别的任务中断
4.CPU在适当的时候去执行底半部
5.至于在何时何地去登记,随便!一旦被登记,CPU的资源也能够获取,底半部的
内容立马得到执行!
6.底半部的实现方法三种:tasklet、工作队列、软中断
八、底半部机制之tasklet
astlet的本质仅仅是延后执行
特点:
1.tasklet本身就是基于软中断实现的;、
2.延后执行的内容都是放在tasklet的一个函数中,此函数又称延后处理函数;
里面可以放不紧急,耗时较长的内容
3.tasklet的延后处理函数工作在中断上下文中,所以不能进行休眠操作
补充:中断上下文: 中断处理的过程(进入中断向量函数,保护现场,执行中断函
数,恢复现场)
进程上下文: 进程的创建,调度,切换,状态修改,进程抢占,休眠,销毁
九、底半部机制之工作队列
特点:
1.工作队列 = 工作 +队列 = 工作的队列 = 队列中的每一个节点就是一个工作
“工作”:延后执行的任务
2.工作队列也是延后执行的一种手段
3.工作队列中每个节点代表着延后执行的某个事,这个事要放在一个函数中,此函数又称为工作节点的延后处理函数
4.工作队列中每一个节点对应的延后处理函数工作在进程上下文中,可以进行休眠操作。
5.工作队列就是为了解决tasklet的延后处理函数不能休眠的问题
将来如果发现延后处理函数中需要做休眠操作,只能采用工作队列,而不能 采用 tasklet
6.工作队列的延后处理函数的效率不如tasklet的延后处理函数,工作队列基于进程,而tasklet基于软中断,tasklet不可休眠,工作队列可以休眠
7.工作队列可以使用默认的
十、底半部机制之软中断
软中断的特点:
1.软中断本质也是延后执行的一种手段
2.软中断的延后处理函数可以运行在多个CPU之上
3.由于第二点,内核要求软中断的延后处理函数要具有可重入性
函数可重入性:
1.尽量避免访问全局变量
2.如果要访问全局变量,记得要进行互斥访问,缺点是大大降低了代码的执行效率
4. tasklet虽然是基于软中断实现,但是其延后处理函数只能运行在一个CPU上
5. 通过第二和第四这两个特点对比,软中断的效率要比tasklet要高
6. 软中断的软件实现,不能采用insmod和rmmod形式的动态加载和卸载,只能静态编译到zImage,无形加大了软中断代码实现的复杂度,就是因为麻烦,所以给你提供了tasklet机制
关于底半部机制的总结:
底半部机制的本质就是延后执行的手段。
tasklet基于软中断,效率高,不可休眠;
工作队列基于进程,效率不如tasklet的延后处理函数,可以休眠
附例程:
点击(此处)折叠或打开