中断的底半部和顶半部
tasklet
工作队列
1、中断的底半部和顶半部
中断在执行的过程中是不能阻塞的,所以希望中断执行的越快越好。所以把中断分成了两个部分,分别是顶半部和底半部、其中顶半部就是前面说的中断,其中是一些硬件的处理代码,希望处理的越快越好。而在中断后续的一些处理过程,内核建议把这些放在中断的底半部执行。
可以有三种方法来实现下半部。分别是软中断、tasklet和工作队列
2、tasklet
初始化:
可以通过调用一个特定函数或者宏来实现
#include <linux/interrupt.h>
struct tasklet_struct {
/* ... */
void (*func)(unsigned long);
unsigned long data;
};
void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data);
DECLARE_TASKLET(name, func, data);
DECLARE_TASKLET_DISABLED(name, func, data);
<pre name="code" class="html">调度tasklet执行 一般在中断处理函数中执行
<pre name="code" class="html">void tasklet_schedule(struct tasklet_struct *t);
确保tasklet 不会再被调度执行一般在模块卸载函数中执行
<pre name="code" class="html">void tasklet_kill(struct tasklet_struct *t);
3、工作队列
工作队列有一个 struct workqueue_struct 类型, 在 <linux/workqueue.h> 中定义. 一个工作队列必须明确的在使用前创建, 使用一个下列的 2 个函数:
初始化工作队列
<pre name="code" class="html">struct workqueue_struct *create_workqueue(const char *name);
初始化work struct
<pre name="code" class="html">INIT_WORK(struct work_struct *work, void (*function)(void *), void *data);
提交工作队列,在中断函数中执行
<pre name="code" class="html">int queue_work(struct workqueue_struct *queue, struct work_struct *work);
取消一个工作队列,一般在模块卸载函数中执行
<pre name="code" class="html">void flush_workqueue(struct workqueue_struct *queue);
void destroy_workqueue(struct workqueue_struct *queue);