0> 概述:
中断分成上下半部目的只有1个:使cpu快速处理完中断。
其实质是把一些事情放到上半部快速执行完, 另一些事情放到下半部,cpu有空了再执行。
实现中中断下半部的方法:
1》 小任务机制 --->tasklet_struct
2》 工作队列机制---->workqueue_struct
Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1> tasklet:
struct tasktlet_struct
{
stucut tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*fun) (unsigneg long); //中断下半部函数
unsigned long date;
}
1》 1.定义并初始化:DECLARE_TASKLET(name , fun, date);
@name:tasklet名字。
@fun:下半部函数。
@date:传给fun的参数。
2. 先定义后初始化:
struct tasklet_struct tsk
void tasklet_init ( struct taskle_struct *t, //&tsk
void (*fun) (unsigned long), //下半部函数
unsigned long date //传给下半部函数的参数
)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2》调度下半部:
/*将初始化的tasklet加到一个链表中, cpu空闲时调度它, 从而调用下半部函数*/
void tasklet_schedule(struct tasklet_struct *tasklet);
NOTE: tasklet工作在中断上下文,所以不可睡眠。in_interrupt()函数判断。
Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2>工作队列
typedef void (*work_func_t)(struct work_struct *work);
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func; //下半部函数
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
1》 共享队列:使用内核提供的共享的默认工作队列system_wq
/linux-3.5/include/linux/workqueue.h
1》 》定义:struct work_struct wk;
2》》初始化:INIT_WORK(struct work_struct *work, //&wk
void (*fun)(void *) //下半部函数
);
3》》调度下半部:
/*将初始化的work_struct 添加到系统队列system_wq中, cpu空闲时调work_struct,从而调下半部函数*/
int schedule_work(struct work_struct *work)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2》创建队列: 使用自己定义的队列
/linux-3.5/include/linux/workqueue.h
1>> 创建队列:
struct workqueue_struct *my_wq;
my_wq = create_workqueue(“lsx_wq”);
2>> 定义并初始化 work_struct: //与分步初始化一样
#define DECLARE_WORK(n, f) \
struct work_struct n = __WORK_INITIALIZER(n, f)
3>> 调度下半部:
/*将初始化的work_struct 添加到我们队列my_wq中, cpu空闲时调work_struct,从而调下半部函数*/
int queue_work(
struct workqueue_struct *wq, //my_wq,自己的队列
struct work_struct *work //初始化的work_struct n
);