Linux内核中的软中断、tasklet和工作队列详解( 二 )
实际上即以软中断类型nr作为偏移量置位每cpu变量irq_stat[cpu_id]的成员变量__softirq_pending , 这也是同一类型软中断可以在多个cpu上并行运行的根本原因 。
- 软中断执行函数
do_softirq-->__do_softirq
执行软中断处理函数__do_softirq前首先要满足两个条件: (1)不在中断中(硬中断、软中断和NMI)。 1 (2)有软中断处于pending状态 。系统这么设计是为了避免软件中断在中断嵌套中被调用 , 并且达到在单个CPU上软件中断不能被重入的目的 。 对于ARM架构的CPU不存在中断嵌套中调用软件中断的问题 , 因为ARM架构的CPU在处理硬件中断的过程中是关闭掉中断的 。 只有在进入了软中断处理过程中之后才会开启硬件中断 , 如果在软件中断处理过程中有硬件中断嵌套 , 也不会再次调用软中断 , because硬件中断是软件中断处理过程中再次进入的 , 此时preempt_count已经记录了软件中断!对于其它架构的CPU , 有可能在触发调用软件中断前 , 也就是还在处理硬件中断的时候 , 就已经开启了硬件中断 , 可能会发生中断嵌套 , 在中断嵌套中是不允许调用软件中断处理的 。 Why?我的理解是 , 在发生中断嵌套的时候 , 表明这个时候是系统突发繁忙的时候 , 内核第一要务就是赶紧把中断中的事情处理完成 , 退出中断嵌套 。 避免多次嵌套 , 哪里有时间处理软件中断 , 所以把软件中断推迟到了所有中断处理完成的时候才能触发软件中断 。需要C/C++ Linux服务器架构师学习资料私信“资料”(资料包括C/C++ , Linux , golang技术 , Nginx , ZeroMQ , MySQL , Redis , fastdfs , MongoDB , ZK , 流媒体 , CDN , P2P , K8S , Docker , TCP/IP , 协程 , DPDK , ffmpeg等) , 免费分享
文章插图
实现原理和实例软中断的调度时机:
- do_irq完成I/O中断时调用irq_exit 。
- 系统使用I/O APIC,在处理完本地时钟中断时 。
- local_bh_enable , 即开启本地软中断时 。
- SMP系统中 , cpu处理完被CALL_FUNCTION_VECTOR处理器间中断所触发的函数时 。
- ksoftirqd/n线程被唤醒时 。下面以从中断处理返回函数irq_exit中调用软中断为例详细说明 。触发和初始化的的流程如图所示:
文章插图
软中断处理流程
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));lockdep_softirq_enter();cpu = smp_processor_id();restart:/* Reset the pending bitmask before enabling irqs */set_softirq_pending(0);local_irq_enable();h = softirq_vec;do {if (pendingkstat_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 (pendingif (pending)wakeup_softirqd();lockdep_softirq_exit();account_system_vtime(current);_local_bh_enable();}
- AMD Zen3 APU内核图提前偷跑:三级缓存质变
- 苹果M1、A14内核设计对比:差别很大
- Linux Kernel 5.10.5发布:禁用FBCON加速滚动特性
- 田伟院士:我眼中的医疗机器人
- Mozilla将默认禁用Firefox中的退格键以防止用户编辑数据丢失
- Linux 5.11开始围绕PCI Express 6.0进行早期准备
- Fedora正在寻求协助 希望加快Linux 5.10 LTS内核测试进度
- Linux Mint 20.1 Ulyssa稳定版已确定延期至2021年初发布
- 英特尔Xe GPU在Linux 5.11上的性能表现不错
- MIPS架构厂商日渐式微 Linux报告其漏洞遭遇困难