软中断知识

本文详细介绍了Linux内核中的软中断机制,包括软中断计数器的作用、如何通过函数调用来增加硬中断计数、软中断的执行流程及__do_softirq函数的具体实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:http://blog.youkuaiyun.com/yiyeguzhou100/article/details/49909787
http://blog.youkuaiyun.com/adaptiver/article/details/6177646
http://yaoyang.blog.51cto.com/7657153/1261841
在说软中断前,先说一下preempt_count()

thread_info中的成员preempt_count,它是一个32位的字段,分为几个部分,:
0-7位: 抢占计数器, 最大值255
8-15位: 软中断计数器, 最大值255
16-27位: 硬中断计数器, 最大值4096
28位: PREEMPT_ACTIVE标志

因此,在hardirq.h中定义了几个宏:

#define PREEMPT_BITS    8
#define SOFTIRQ_BITS    8
#define HARDIRQ_BITS    12

#define PREEMPT_SHIFT    0
#define SOFTIRQ_SHIFT    (PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT    (SOFTIRQ_SHIFT + SOFTIRQ_BITS)

#define PREEMPT_OFFSET    (1UL << PREEMPT_SHIFT)
#define SOFTIRQ_OFFSET    (1UL << SOFTIRQ_SHIFT)
#define HARDIRQ_OFFSET    (1UL << HARDIRQ_SHIFT)

因此, 函数调用add_preempt_count(HARDIRQ_OFFSET)是增加其中硬中断的计数.

in_interrupt()–>irq_count()–>(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK | NMI_MASK))
其中SOFTIRQ_MASK是软中断计数器所在位的全部为1的数。掩码就是全为1,如PREEMPT_BITS的掩码为11111111。

如:在中断退出时irq_exit有:

void irq_exit(void)
{
        account_system_vtime(current);
        trace_hardirq_exit();
        sub_preempt_count(IRQ_EXIT_OFFSET);
        if (!in_interrupt() && local_softirq_pending())                       检验是否在软中断或者硬中断中,和检验是否有软中断挂起需要执行
                invoke_softirq();

        rcu_irq_exit();
#ifdef CONFIG_NO_HZ
        /* Make sure that timer wheel updates are propagated */
        if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())
                tick_nohz_stop_sched_tick(0);
#endif
        preempt_enable_no_resched();
}

分析__do_softirq函数
asmlinkage void __do_softirq(void)
{
        struct softirq_action *h;
        __u32 pending;
        int max_restart = MAX_SOFTIRQ_RESTART;
        int cpu;

        pending = local_softirq_pending();                                                   提取出挂起的软中断掩码,先将其保存起来,以免发生中断后不可靠
        account_system_vtime(current);                                                      

        __local_bh_disable((unsigned long)__builtin_return_address(0));                       软件抢占计数加1,即屏蔽其他的软中断
        lockdep_softirq_enter();                                                                 软中断上下文计数加1

        cpu = smp_processor_id();
restart:
        /* Reset the pending bitmask before enabling irqs */
        set_softirq_pending(0);                                                                  先把软中断任务清空

        local_irq_enable();

        h = softirq_vec;

        do {
                if (pending & 1) {                                              //这是针对每大类,如:TASKLET_SOFTIRQ  HI_SOFTIRQ等
                        int prev_count = preempt_count();
                        kstat_incr_softirqs_this_cpu(h - softirq_vec);

                        trace_softirq_entry(h, softirq_vec);
                        h->action(h);                                                           将一个个软中断提取出来并执行其操作函数
                        trace_softirq_exit(h, softirq_vec);
                        if (unlikely(prev_count != preempt_count())) {
                                printk(KERN_ERR "huh, entered softirq %td %s %p"
                                       "with preempt_count %08x,"
                                       " exited with %08x?\n", h - softirq_vec,
                                       softirq_to_name[h - softirq_vec],
                                       h->action, prev_count, preempt_count());
                                preempt_count() = prev_count;
                        }

                        rcu_bh_qs(cpu);
                }
                h++;
                pending >>= 1;
        } while (pending);

        local_irq_disable();

        pending = local_softirq_pending();
        if (pending && --max_restart)                                                        最多就只循环十次
                goto restart;

        if (pending)
                wakeup_softirqd();                                                                唤醒软中断的守护线程

        lockdep_softirq_exit();                                                    软中断上下文计数减1

        account_system_vtime(current);
        _local_bh_enable();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值