Linux驱动开发-中断分层机制笔记 6
Posted hntea-hong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux驱动开发-中断分层机制笔记 6相关的知识,希望对你有一定的参考价值。
中断分层机制—tasklet
中断上下文
因为中断产生时会打断当前占用CPU的进程,为尽量提高进程的运行效率,不会卡顿,从而使中断服务程序分为顶半部和底半部两个部分
顶部分是用来处理应急事件,特别是硬件相关;之后将CPU使用权交个当前进程
底部分(不着急处理的,任务繁琐的)则等待CPU空闲时,既内核线程觉得有能力运行时才去执行。
注意事项
i. 中断上下文代码绝对不可以停止运行
中断处理程序不能调用schedule_timeout()等随眠函数放弃CPU
在中断处理函数中调用一个内核API之前,应该仔细分析,确保内部不会触发阻塞等待.
为了中断处理函数中保存临界区,不能使用互斥体,应该使用自旋锁代替互斥体,只有在不得不用的时候采用
中断处理函数不能与用户空间直接交互数据,应为它们经由进程上下文与用户空间建立连接
中断函数不必是可重用的
中断函数可以被更高优先级IRQ的中断打断
a) 快速中断不可被打断:既执行快速中断时,处理器所有中断都会被屏蔽
b) 同步中断:有处理器本身执行某些指令产生;如:
异常:用于报告严重的运行时错误
软中断:
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 和处理函数:
DECLARE_TASKLET(my_tasklet,my_tasklet_func,data);
解释:将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)
/*释放中断*/
Takslet驱动测试–【无中断测试】
/**********************************
作者: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);
以上是关于Linux驱动开发-中断分层机制笔记 6的主要内容,如果未能解决你的问题,请参考以下文章