中断是为了更好的提高任务运行效率的方式,不知道中断是什么的朋友,可以先去学习一下中断的基本概念。下面正式开始:
本文分为两个部分,Linux中断需要了解的知识以及驱动使用中断的方法。
中断号
每一个中断都有一个中断号,操作系统可以通过中断号来区分中断,Linux的中断号可以在终端输入"cat /proc/interrupts"命令查看
Linux中断类型分类
中断可以分为外部中断(硬件中断)以及内部中中断(异常),几乎所有中断都可以分为这两个部分,Linux中断也是如此。
Linux中断会使用到很多API函数,我们在后面讲解。
中断上下文
为什么要使用中断上下文呢?中断固然好,但是不是很建议CPU进入中断的时间很长,理由如下:
1.不能响应其他中断可能会遗漏其他中断
2.正常应用程序不能按时执行
3.部分CPU是可以嵌套的,很有可能会让中断越嵌套越深,容易导致栈溢出
Linux为了能够防止上述情况发生,采用了中断上下文的方式,在Linux中,中断可以分为上文和下文,上文就是中断服务函数,下文就是专门处理运行时间较长的工作
中断上文(硬件中断)
当收到某一个信号时,开始中断进入中断服务函数,在中断服务函数中执行时间严格受限的指令。
中断下文(软件中断)
中断下文就是将任务交给内核,在内核中后续执行,这样的方式,在Linux中有几种常见机制。
1.tasklet机制
2.workque工作队列
tasklet机制
tasklet的实现方式是基于软中断的模式。
软中断也是一种实现中断下文的机制,但是,需要大改代码,效率较低,所以不推荐
tasklet的存储方式就是以链表的方式进行储存,放入到一个内核线程的软中断链表(SOFTIRQD)中,下面是一个tasklet的存储结构
struct tasklet_struct{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
bool use_callback;
union
{
void (*func)(unsigned long data);
void (*callback)(struct tasklet_struct *t);c
};
unsigned long data;
};
这里有两个不同优先级的链表,tasklet_vec(普通优先级)和 tasklet_hi_vec(高优先级),分别对应不同的调度API。
这两个链表在系统上,分别注册了自己的软中断。所以在软中断中,所有就绪的tasklet会被逐一从链表中取出运行(执行tasklet_struct中的callback或func)。
另外,每个CPU都各自拥有上述两个链表,但激活tasklet时,只会加入到当前CPU的链表上,所以同一个tasklet不会有并发执行产生。
API函数会在下一个部分进行讲解,目前使用主流的处理中断下半部分的方式就是使用tasklet机制
工作队列(workque)
工作队列不像tasklet一样建立一个节点,内核启动后会创建一个工作线程和工作队列,直接使用线程来工作。