【linux内核分析与应用-陈莉君】中断下半部处理机制

本文详细介绍了中断处理机制,包括中断的基本机制、中断的下半部分、软中断、小任务(tasklet)机制、工作队列(workqueue)机制等内容。通过本文的学习,读者可以了解不同中断处理机制的特点及适用场景。

目录

 

1.中断的基本机制

2.中断的下半部分

2.1软中断

2.2小任务(tasklet)机制

2.3编写自己的小任务并调度

2.4工作队列(workqueue)机制

3.总结

4.动手实践与参考资料与思考


1.中断的基本机制

中断服务程序一般都是在终端请求关闭的条件下执行的,以避免嵌套使得中断控制复杂化.
但是中断是一个随机事件,它随时可以到来.如果关中断的时间太长,CPU就不能及时响应
其他的中断请求.从而造成中断的丢失.因此内核的目标就是尽可能快地处理完中断请求,
尽其所能把更多的处理往后推迟.
如图是中断的基本模型,在终端向量表中填入中断处理程序的入口地址,然后跳到该程序
执行.

2.中断的下半部分

随着系统的不断复杂,中断处理函数需要处理的事情越来越多,多到都来不及接受新的中断,
于是发生了中断丢失,这显然是不可以的,于是内核将中断分成两个部分,一个是上半部,这
一部分是不可中断的,一个是下半部,这个是可中断的,上半部-也就是中断服务程序内核会立刻
处理,而下半部-也就是一些内核的函数留着稍后处理,在中断的下半部分处理机制中,提供了
好几种机制:

2.1软中断

首先看一下软中断机制,不管是中断的上半部分还是中断的下半部分,都是一种概念,实际上
都是内核中的一个函数,这些函数写好以后什么时候被执行以及如何执行,这个是内核必须
同一管理的.在上一讲中终端机制中我们说了中断注册函数request_irq,它将中断服务例程
添加到中断请求队列中,其执行是由do_irq函数完成的,与此对应我们可以通过open_softirq
添加下半部分处理函数,其执行是由do_softirq函数完成的,也就是软中断机制来完成的.

软中断的类型:
1.soft_irq
2.tasklet
3.workqueue

每个软中断在内核中都是以soft_irq_action来表示的,内核目前实现了10种软中断.
定义在interrupt.h这个文件中.如本小结第二个图.

2.2小任务(tasklet)机制

小任务机制是IO驱动程序中实现可延迟函数的首选方法,小任务和工作队列都是
延迟执行工作的一种机制.其实现是基于软中断的.但它们更易于使用,因而更适
合于设备驱动程序,所谓小任务是什么意思呢?就是执行一些mini型的任务.
内核中的小任务数据结构:
struct tasklet_struct;
数据结构中func就是下半部要推迟执行的函数;
data是传递给func这个函数的唯一参数;
count是小任务的引用计数器,如果它不为0,则小任务被禁止,不允许执行,
只有当它为0的时候,小任务才被集合并且是在被设置成挂起的时候小任务
才能够执行.

2.3编写自己的小任务并调度

2.4工作队列(workqueue)机制

前面的机制不论如何折腾,实际上有一点是不会变的,它们都是在中断上下文中,
说明它们是不可挂起的,而且由于是串行执行,因此只要有一个时间处理较长的话,
就会导致其它中断响应的延迟,为了完成这些不可能完成的任务,于是出现了工作
队列机制,工作队列说白了就是一组内核线程作为中断守护线程来使用,多个中断
可以放在一个线程中,也可以每个中断分配一个线程,工作队列对线程进行封装,
使用起来更方便,因为工作队列是线程,所以我们可以使用所有可以在线程中使用的
方法.

内核中的工作队列数据结构:
struct work_struct;
数据结构中func钩子函数就是推迟要执行的函数;
data是传递给func这个函数的唯一参数;

每CPU工作队列结构:
如果是多线程,内核就要根据当前CPU个数为每个CPU创建一个cpu_workqueue_struct
结构,简称为cws结构,在这个结构中主要是维护了一个任务队列以及内核线程需要睡眠
的等待队列,另外还维护了一个任务上下文(thread).

工作队列的运行机制:
当用户调用工作队列初始化函数的时候,对工作队列进行初始化以后,内核就开始为用户
分配一个工作队列对象并且将其挂到一个全局的workqueue中,然后内核根据当前CPU的情况
为workqueue对象分配与CPU个数相同的cpu_workqueue_struct对象,每一个cpu_workqueue_struct对象
都会有一个任务队列,紧接着内核为cpu_workqueue_struct对象分配一个内核线程,也就是
内核的daemon,去处理每个队列中的任务.自此,用户调用初始化接口将工作队列初始化完毕,
返回workqueue的指针,workqueue初始化完毕以后将用户运行的上下文环境就构建起来了.
但是具体还没有可执行的任务,所以需要定义具体的work_struct对象,然后将work_struct
加入到任务队列中.内核会唤醒内核守护线程去处理该任务.

3.总结

什么时候使用哪种中断处理机制?
request_irq挂的是中断函数,这个函数要尽量的简单,只做必须在
屏蔽中断情况下要做的事情,中断的其他部分都要放在下半部分完成.
软中断的使用原则很简单,最好不用,它甚至不算一种真正的中断处理机制,只是tasklet的实现基础.
工作队列也要少用,如果不是必须要用线程才用的某些机制,就不要使用工作队列.

为什么对工作队列机制做了比较详细的讲解,是希望大家在这种设计机制中能够得到启发,
其实对中断来说只是对终端做了简单的处理,大部分工作是在驱动程序中完成的,除了上述
情况以外,一般都是用小任务tasklet机制,即使是下半部分,也是在做必须在中断中要做的
事情,如保存数据帧,其他都是交给驱动程序去做的.

4.动手实践与参考资料与思考

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值