1、中断上下文
a) 因为中断产生时会打断当前占用CPU的进程,为尽量提高进程的运行效率,不会卡顿,从而使中断服务程序分为顶半部和底半部两个部分
b) 顶部分是用来处理应急事件,特别是硬件相关;之后将CPU使用权交个当前进程
c) 底部分(不着急处理的,任务繁琐的)则等待CPU空闲时,既内核线程觉得有能力运行时才去执行。
d) 注意事项
i. 中断上下文代码绝对不可以停止运行
1. 中断处理程序不能调用schedule_timeout()等随眠函数放弃CPU
2. 在中断处理函数中调用一个内核API之前,应该仔细分析,确保内部不会触发阻塞等待.
3. 为了中断处理函数中保存临界区,不能使用互斥体,应该使用自旋锁代替互斥体,只有在不得不用的时候采用
4. 中断处理函数不能与用户空间直接交互数据,应为它们经由进程上下文与用户空间建立连接
5. 中断函数不必是可重用的
6. 中断函数可以被更高优先级IRQ的中断打断
a) 快速中断不可被打断:既执行快速中断时,处理器所有中断都会被屏蔽
b) 同步中断:有处理器本身执行某些指令产生;如:
i. 异常:用于报告严重的运行时错误
ii. 软中断:
2、中断分层实现,底半部处理方法
a) 任务:struct tasklet
b) 工作队列: struct work_struct
c) 软中断:
3、tasklet 编程实现相关函数
a) 数据结构:
struct tasklet_struct
{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long); /*需要驱动完成的函数*/
unsigned long data; /*传递给func函数?*/
};
b) 主要特征
Main feature differing them of generic softirqs: tasklet
is running only on one CPU simultaneously.
Main feature differing them of BHs: different tasklets
may be run simultaneously on different CPUs.
c) 定义tasklet: struct tasklet my_tasklet
d) 定义处理函数:void my_tasklet_func(unsigned long)
e) 关联tasklet 和处理函数:
i. DECLARE_TASKLET(my_tasklet,my_tasklet_func,data);
ii. 解释:将my_tasklet 与处理函数绑定,并将data 作为参数传递给my_task_func
f) 调度(交给系统自行处理):tasklet_schedule(&my_tasklet)
4、使用tasklet作为中断底半部的设备驱动程序模板
.
/*1.定义结构体*/
struct tasklet_struct my_tasklet;
/*2.编写底半部函数*/
void xxx_do_tasklet(unsigned long x)
{
...
}
/*3.关联函数*/
DECLARE_TASKLET(my_tasklet,xxx_do_tasklet,0);
/*4.中断处理顶半部*/
static irqreturn_t xxx_interrupt(int irq, void *dev_id)
{
...
/*提交takslet 并启动调度*/
tasklet_schedule(&my_tasklet);
...
}
/*5.模块加载*/
module_init(xxxx)
{
.....
/*申请中断*/
......
}
/*6.模块卸载*/
module_exit(yyyy)
{
/*释放中断*/
}
/**********************************
作者:hntea
时间:2016/3/14
驱动功能:tasklet 模板功能测试
**********************************/
#include<linux/init.h>
#include<linux/module.h>
#include<linux/interrupt.h>
#include<linux/time.h>
/*定义 tasklet */
struct tasklet_struct my_tasklet;
/*定义服务函数,任务提交后只执行一次*/
static void my_taskfunc(unsigned int x)
{
printk("I am taskfunc\n");
printk("My argument is:%d\n",x);
}
/*关联结构体和服务函数*/
DECLARE_TASKLET(my_tasklet,my_taskfunc,1);
static int irqTask_init(void)
{
tasklet_schedule(&my_tasklet); /*一般提交任务在中断处理函数中提交,实现分层*/
return 0;
}
static void irqTask_exit(void)
{
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Hntea");
module_init(irqTask_init);
module_exit(irqTask_exit);