中断服务下半部之老大-软中断softirq
Sailor_forever sailing_9806@163.com 转载请注明
http://blog.csdn.net/sailor_8318/archive/2008/07/13/2645180.aspx
【摘要】本文详解了中断服务下半部机制的基础softirq。首先介绍了其数据结构,分析了softirq的执行时机及流程。接着介绍了软中断的API及如何添加自己的软中断程序,注册及其触发。最后了介绍了用于处理过多软中断的内核线程ksoftirqd,分析了触发ksoftirqd的原则及其执行流程。
【关键字】中断服务下半部,软中断softirq,softirq_action,open_softirq(),raise_softirq,ksoftirqd
1 软中断结构softirq_action
软中断使用得比较少,但其是tasklet实现的基础。而tasklet是下半部更常用的一种形式。软中断是在编译期间静态分配的。它不像tasklet那样能被动态地注册或去除。软中断由softirq_action结构表示,它定义在<linux/interrupt.h>中:
246struct softirq_action
247{
248 void (*action)(struct softirq_action *);
250};
Action: 待执行的函数;
Data: 传给函数的参数,任意类型的指针,在action内部转化
kernel/softirq.c中定义了一个包含有32个该结构体的数组。
static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp;
每个被注册的软中断都占据该数组的一项。因此最多可能有32个软中断,因为系统靠一个32位字的各个位来标识是否需要执行某个软中断。注意,这是注册的软中断数目的最大值没法动态改变。在当前版本的内核中,这个项中只用到6个。。
2 执行软中断
一个注册的软中断必须在被标记后才会执行。这被称作触发软中断(raising the softirq )。通常,中断处理程序会在返回前标记它的软中断,使其在稍后被执行。于是,在合适的时刻,该软中断就会运行。在下列地方,待处理的软中断会被检查和执行:
² 从一个硬件中断代码处返回时。
² 在ksoftirqd内核线程中。
² 在那些显式检查和执行待处理的软中断的代码中,如网络子系统中。
不管是用什么办法唤起,软中断都要在do_softirq()中执行。如果有待处理的软中断,do_softirq()会循环遍历每一个,调用它们的处理程序。
252#ifndef __ARCH_HAS_DO_SOFTIRQ
254asmlinkage void do_softirq(void)
255{
259 if (in_interrupt()) //中断函数中不能执行软中断
260 return;
264 pending = local_softirq_pending();
266 if (pending) //只有有软中断需要处理时才进入__do_softirq
267 __do_softirq();
195/*
196 * 最多循环执行MAX_SOFTIRQ_RESTART 次若中断,若仍然有未处理完的,则交由softirqd 在适当的时机处理。需要协调的是延迟和公平性。尽快处理完软中断,但不能过渡影响用户进程的运行。
203 */
204#define MAX_SOFTIRQ_RESTART 10
206asmlinkage void __do_softirq(void)
207{
208 struct softirq_action *h;
210 int max_restart = MAX_SOFTIRQ_RESTART;
213 pending = local_softirq_pending();
214 account_system_vtime(current);
216 __local_bh_disable((unsigned long)__builtin_return_address(0));
219 cpu = smp_processor_id();
221 /* Reset the pending bitmask before enabling irqs */
226 h = softirq_vec;