现在的位置: 首页 > 综合 > 正文

【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】中断服务下半部之老大-软中断softirq

2013年10月02日 ⁄ 综合 ⁄ 共 2510字 ⁄ 字号 评论关闭

 

中断服务下半部之老大-软中断softirq

 

Sailor_forever  sailing_9806@163.com 转载请注明

http://blog.csdn.net/sailor_8318/archive/2008/07/13/2645180.aspx

 

【摘要】本文详解了中断服务下半部机制的基础softirq。首先介绍了其数据结构,分析了softirq的执行时机及流程。接着介绍了软中断的API及如何添加自己的软中断程序,注册及其触发。最后了介绍了用于处理过多软中断的内核线程ksoftirqd,分析了触发ksoftirqd的原则及其执行流程。

 

【关键字】中断服务下半部,软中断softirqsoftirq_actionopen_softirq()raise_softirqksoftirqd

 

 

1      软中断结构softirq_action. 1

2      执行软中断... 2

3      软中断的API 4

3.1       分配索引号... 4

3.2       软中断处理程序... 5

3.3       注册软中断处理程序... 6

3.4       触发软中断... 6

4      ksoftirqd. 7

4.1       Ksoftirqd的诞生... 7

4.2       启用Ksoftirqd的准则... 8

4.3       Ksoftirqd的实现... 8

 

1       软中断结构softirq_action

软中断使用得比较少,但其是tasklet实现的基础。而tasklet是下半部更常用的一种形式。软中断是在编译期间静态分配的。它不像tasklet那样能被动态地注册或去除。软中断由softirq_action结构表示,它定义在<linux/interrupt.h>:

 246struct softirq_action

 247{

 248        void    (*action)(struct softirq_action *);

 249        void    *data;

 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

 253

 254asmlinkage void do_softirq(void)

 255{

 256        __u32 pending;

 257        unsigned long flags;

 258

 259        if (in_interrupt()) //中断函数中不能执行软中断

 260                return;

 261

 262        local_irq_save(flags);

 263

 264        pending = local_softirq_pending();

 265

 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;

 209        __u32 pending;

 210        int max_restart = MAX_SOFTIRQ_RESTART;

 211        int cpu;

 212

 213        pending = local_softirq_pending();

 214        account_system_vtime(current);

 215

 216        __local_bh_disable((unsigned long)__builtin_return_address(0));

 217        trace_softirq_enter();

 218

 219        cpu = smp_processor_id();

 220restart:

 221        /* Reset the pending bitmask before enabling irqs */

 222        set_softirq_pending(0);

 223

 224        local_irq_enable();

 225

 226        h = softirq_vec;

 227

抱歉!评论已关闭.