中断的上下文与进程上下文并没有什么瓜葛,当执行一个中断处理函数时,内核处于中断上下文。由于中断相当于打断了当前执行的程序,而且中断也没有后备的进程,所以中断上下文不可以睡眠(注意某些函数会睡眠),中断处理也必须做到迅捷,有一定的时限要求。 中断处理程序存在希望中断程序运行的尽量快以及希望中断处理程序完成的工作量多这一对矛盾。因此我们一般将中断分为上下两个部分,成为上半部,下半部。上半部完成有严格时限的工作(必须),例如回复硬件等,这些工作都是在禁止其他中断情况下进行的。能够延后执行的都放在下半部进行。 上半部只能通过中断处理程序实现,下半部的实现目前有3种实现方式,分别为:1、软中断、2、tasklet 3、工作队列(work queues). 软中断用的比较少,这里不做介绍。 tasklet运行于中断的上下文,不允许睡眠
1)定义一个tasklet_struct结构(也可以通过宏来创建)
struct tasklet_struct mytasklet;
2)定义一个处理函数(执行延后的工作任务)
void my_tasklet_func(unsigned long);
3)将tasklet结构与my_tasklet_func(data)函数相关联(将处理程序封装到tasklet_struct)
tasklet_init(&my_tasklet, my_tasklet_func, data);
4)调度tasklet
tasklet_schedule(&my_tasklet);
工作队列的本质就是将工作交给内核线程events处理, 运行在进程的上下文中,工作队列允许睡眠 我们把推后的任务称之为工作,描述他的数据结构为work_struct.这些工作以队列结构组织成工作队列(workqueue),其数据结构为
workqueue_struct.而工作线程就是负责执行工作队列中的工作。系统默认的工作线程为events。
1)定义一个工作队列
struct work_struct my_wq; 2 )定义一个处理函数 (执行延后的工作任务)
void my_wq_func(unsigned long) ; 3)初始化工作队列并将其与处理函数绑定(将处理程序封装成了一个work_struct)
INIT_WORK(&my_wq, my_wq_func); 4)调度工作队列执行
schedule_work(&my_wq);
|