您的位置:首页 > 其它

中断分层技术

2015-08-29 20:05 190 查看
当Linux系统在处理中断响应时,若有新的中断产生,Linux系统对新中断的处理方法与正在处理的中断类型有关,分为慢速中断和快速中断两种情况。

慢速中断:当处理慢速中断时,中断总开关是不关闭的,允许别的中断产生。例如正在处理串口慢速中断,此时网卡产生中断,则cpu会转去执行网卡中断,执行完网卡中断后才继续执行串口中断;若正在处理串口慢速中断,此时串口产生新的中断,则cpu会忽略这次新的中断。

快速中断:在处理快速中断的过程中,系统不会接收新的中断,即会忽略所有新中断。

从以上可以看出,Linux系统有时会忽略产生的中断,这会导致一些中断无法得到应有的处理。采用中断分层技术能减少中断丢失的概率。

一般来说,中断处理函数要完成的工作有与硬件密切相关的,也有与硬件关联不大的操作。中断分层技术将与硬件密切相关的操作作为上部分,与硬件关联不大的操作作为下半部。上半部依然由中断处理函数来完成,下半部不设置在中断处理函数中执行,从而减少了中断处理函数的工作,进而缩短中断处理的时间。

上半部:当中断发生时,它进行相应地硬件读写,并“登记”该中断。通常由中断处理程序充当上半部。

下半部:在系统空闲的时候对上半部“登记”的中断进行后续处理。

中断分层方式:软中断、tasklet、工作队列(主流)

工作队列是一种将任务推后执行的形式,他把推后的任务交由一个内核线程去执行。这样如果在中断函数中使用中断分层(工作队列方式),中断函数的第二部分会在进程上下文执行,它允许重新调度甚至睡眠。每个被推后的任务叫做“工作”,由这些工作组成的队列称为工作队列。工作队列的本质就是将工作交给内核线程处理,因此其可以用内核线程替换。但是内核线程的创建和销毁对编程者的要求较高,而工作队列实现了内核线程的封装,不易出错,所以推荐使用工作队列。



当工作队列中的工作执行完后,该工作就会被删除。

内核使用struct workqueue_struct来描述一个工作队列;

struct workqueue_struct
{
struct cpu_workqueue_struct *cpu_wq;
struct list_head list;
const char *name; /*workqueue name*/
int singlethread;
int freezeable; /* Freeze threads during suspend */
int rt;
};


内核使用struct work_struct来描述一个工作项;

struct work_struct
{
atomic_long_t data;
struct list_head entry;
work_func_t func;
};


work_struct 结构中最重要的成员是func,该成员是该工作项要执行的函数。

使用工作队列:

①创建工作队列:create_workqueue;创建工作队列首先要遵守“GPL”协议,不然会报错

②创建工作:INIT_WORK;

③提交工作:queue_work,提交工作后并不是马上运行,由内核空闲时内核线程会运行创建的工作队列

在大多数情况下,驱动并不需要自己创建工作队列,只需要定义工作,然后将工作提交到内核已经定义好的工作队列Keventd_wq中。

提交工作到默认队列:schedule_work

#include <linux/init.h>
#include <linux/module.h>

struct work_struct *work1;

MODULE_LICENSE("GPL");

void work1_func(struct work_struct *work)
{
printk("this is work1->\n");
}

int init_que(void)
{
//创建工作
work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);
INIT_WORK(work1, work1_func);

//挂载(提交)工作
schedule_work(work1);

return 0;
}

void clean_que()
{

}

module_init(init_que);
module_exit(clean_que);


在中断处理程序中,一般工作队列的创建工作在内核模块的安装部分完成,提交工作在中断处理函数中完成,则发生中断后内核线程就能找到工作项并执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: