summary

softirq 真正干活的函数是__do_softirq。 linuxv3.11内核里能够执行__do_softirq,有如下调用, 这里指真正执行softirq的地方,不是触发(设置)softirq标志 !!!

  1. 每个硬中断退出的时。
  2. 当bh使能的时。
  3. 发送回环报文时。

case1 每个硬中断退出的时候。

call trace

1
2
3
> irq_exit
> > invoke_softirq
> > > __do_softirq

irq_exit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
350 /*
351  * Exit an interrupt context. Process softirqs if needed and possible:
352  */
353 void irq_exit(void)
354 {355 #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
356         local_irq_disable();
357 #else
358         WARN_ON_ONCE(!irqs_disabled());
359 #endif
360
361         account_irq_exit_time(current);
362         trace_hardirq_exit();
363         sub_preempt_count(HARDIRQ_OFFSET);
364         if (!in_interrupt() && local_softirq_pending())
365                 invoke_softirq();
366
367         tick_irq_exit();
368         rcu_irq_exit();
369 }

invoke_softirq

1
2
3
4
5
6
7
329 static inline void invoke_softirq(void)
330 {331         if (!force_irqthreads)
332                 __do_softirq();
333         else
334                 wakeup_softirqd();
335 }

case2 使能bh的时候

call trace

1
2
3
4
5
> local_bh_enable
> > _local_bh_enable_ip
> > > do_softirq
> > > > (x86_64特有的)call_softirq
> > > > __do_softirq

local_bh_enable

1
2
3
4
5
184 void local_bh_enable(void)
185 {186         _local_bh_enable_ip(_RET_IP_);
187 }
188 EXPORT_SYMBOL(local_bh_enable);

_local_bh_enable_ip

NOTE: 使能bh的时候,刚开始抢占还是禁止的。只有软中断处理完了后,抢占才使能的。 顺便说一下,使能bh时,有可能发生进程切换(见preempt_check_resched).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
157 static inline void _local_bh_enable_ip(unsigned long ip)
158 {159         WARN_ON_ONCE(in_irq() || irqs_disabled());
160 #ifdef CONFIG_TRACE_IRQFLAGS
161         local_irq_disable();
162 #endif
163         /*
164          * Are softirqs going to be turned on now:
165          */
166         if (softirq_count() == SOFTIRQ_DISABLE_OFFSET)
167                 trace_softirqs_on(ip);
168         /*
169          * Keep preemption disabled until we are done with
170          * softirq processing:
171          */
172         sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1);
173
174         if (unlikely(!in_interrupt() && local_softirq_pending()))
175                 do_softirq();
176
177         dec_preempt_count();
178 #ifdef CONFIG_TRACE_IRQFLAGS
179         local_irq_enable();
180 #endif
181         preempt_check_resched();
182 }

do_softirq根据不同的体系机构有不同的版本。

当对应的硬件体系里没有定义do_softirq时,使用 kernel/softirq.c中通用的do_softirq`.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
286 #ifndef __ARCH_HAS_DO_SOFTIRQ
287
288 asmlinkage void do_softirq(void)
289 {290         __u32 pending;
291         unsigned long flags;
292
293         if (in_interrupt())
294                 return;
295
296         local_irq_save(flags);
297
298         pending = local_softirq_pending();
299
300         if (pending)
301                 __do_softirq();
302
303         local_irq_restore(flags);
304 }
305
306 #endif

而对于X86_64,有其自己的定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 92 extern void call_softirq(void);
 93
 94 asmlinkage void do_softirq(void)
 95 { 96         __u32 pending;
 97         unsigned long flags;
 98
 99         if (in_interrupt())
100                 return;
101
102         local_irq_save(flags);
103         pending = local_softirq_pending();
104         /* Switch to interrupt stack */
105         if (pending) {106                 call_softirq();
107                 WARN_ON_ONCE(softirq_count());
108         }
109         local_irq_restore(flags);
110 }

其中call_softirq是个用汇编语言写的一个函数定义在 arch/x86/kernel/entry_64.S

netif_rx_ni

这一块的理解不是很透,仅以一个具体的例子来说明。发送回环报文.

发送回环报文

call trace

1
2
3
4
> dev_loopback_xmit
> > netif_rx_ni
> > do_softirq
> > > __do_softirq

loopback 报文会通过netif_rx函数,被重新放回到 per_cpu变量softnet_data下的队列input_pkt_queue里, 同时激发napi调用,进而激发软中断调用(只是设置标志位,不是真正调用)

另外,注意netif_rx_ni里没有禁止bh调度,而是只是禁止了抢占(preempt_disable).

dev_loopback_xmit
1
2
3
4
5
6
7
8
9
10
11
2765 int dev_loopback_xmit(struct sk_buff *skb)
2766 {2767         skb_reset_mac_header(skb);
2768         __skb_pull(skb, skb_network_offset(skb));
2769         skb->pkt_type = PACKET_LOOPBACK;
2770         skb->ip_summed = CHECKSUM_UNNECESSARY;
2771         WARN_ON(!skb_dst(skb));
2772         skb_dst_force(skb);
2773         netif_rx_ni(skb);
2774         return 0;
2775 }
netif_rx_ni
1
2
3
4
5
6
7
8
9
10
11
12
13
3267 int netif_rx_ni(struct sk_buff *skb)
3268 {3269         int err;
3270
3271         preempt_disable();
3272         err = netif_rx(skb);
3273         if (local_softirq_pending())
3274                 do_softirq();
3275         preempt_enable();
3276
3277         return err;
3278 }
3279 EXPORT_SYMBOL(netif_rx_ni);

Posted by Martin Sep 23rd, 2013 10:36 am  irqs

http://martinbj2008.github.io/blog/2013/09/23/where-softirq-is-invoked/

Where Softirq Is Invoked相关推荐

  1. softirq/tasklet/workqueue的区别

    2011年威盛Linux software的笔试题,我想了半天,就想出了工作队列允许睡眠...真后悔驱动没能深入看看 softirq和tasklet都属于软中断,tasklet是softirq的特殊实 ...

  2. 中断底半部:softirq、tasklet、workqueue

    为了在中断执行时间尽可能短和中断处理需完成大量工作之间找到一个平衡点,Linux 将中断处理程序分解为两个半部:顶半部(top  half)和底半部(bottom half). 顶半部完成尽可能少的比 ...

  3. linux cpu softirq,linux softirq机制

    Copyright © 2003 by 詹荣开 E-mail:zhanrk@sohu.com Linux-2.4.0 Version 1.0.0,2003-2-14 摘要:本文主要从内核实现的角度分析 ...

  4. Linux内核的Softirq机制

    前言  中断服务程序往往都是在CPU关中断的条件下执行的,以避免中断嵌套而使控制复杂化.但是CPU关中断的时间不能太长,否则容易丢失中断信号.为此,Linux将中断服务程序一分为二,各称作" ...

  5. Linux中断(interrupt)子系统之五:软件中断(softIRQ)

    转自:http://blog.csdn.net/droidphone/article/details/7518428 软件中断(softIRQ)是内核提供的一种延迟执行机制,它完全由软件触发,虽然说是 ...

  6. 你应该知道Linux内核softirq

    说起这个softirq ,很多人还是一头雾水,觉得这个是什么东西,跟tasklets 和 workqueue有什么不同. 每次谈到这个,很多人,包括我,都是有点紧张,特别是面试的时候,因为你一旦说错了 ...

  7. Linux内核深入理解中断和异常(7):中断下半部:Softirq, Tasklets and Workqueues

    Linux内核深入理解中断和异常(7):中断下半部:Softirq, Tasklets and Workqueues rtoax 2021年3月 0x00-0x1f architecture-defi ...

  8. ERROR 1442 (HY000):because it is already used by statement which invoked this stored function/tr

    看到mysql的触发器,随手写了一个: mysql> create trigger t_ai_test -> after insert on test -> for each row ...

  9. 设备树学习(二十三、番外篇-中断子系统之softirq)

    既然开始学了,那么还是一次把中断的所有知识都系统的学一下.刚好有蜗窝大神的博客做指引. http://www.wowotech.net/irq_subsystem/soft-irq.html 一.前言 ...

最新文章

  1. linux实验磁盘管理,从0到1学习网络安全 【Linux实验篇-LVM 磁盘管理】
  2. 判断一颗二叉树是否为搜索二叉树和完全二叉树
  3. 前端要给力之:代码可以有多烂?
  4. php连接postgresql
  5. 苹果4s忘记id密码怎么办_苹果电脑 / Mac 忘记了开机密码怎么办?
  6. PHP生成日历(实例详解)
  7. Java OutputStream close()方法与示例
  8. oracle 10g rac 包root.sh报错,案例:Oracle Rac root.sh报错 Failed to create keys in the OLR
  9. c语言数组处理实验报告心得体会,C语言实验报告总结计划数组.doc
  10. 问题五十九:怎么求一元六次方程在区间内的所有不相等的实根(1)
  11. bigdecimal 怎么做除法_面向对象之BigDecimal
  12. 《电子商务安全》考试重点/学习重点
  13. python就业班2017_2017黑马Python就业班视频教程
  14. python rgb565_读取RGB565格式的图像
  15. mysql schemata_SCHEMATA · xiaoboluo768/mysql-system-schema Wiki · GitHub
  16. FFmpeg将多张图片合成视频
  17. 39、C++定义一个类,实现向量的加减运算
  18. 警猫眼App:闲置安卓旧手机DIY变成安防监控云端摄像头
  19. 一款逼疯妹子的撩妹神器
  20. 计算机文档排版考试,Word和WPS通用的文档排版技巧

热门文章

  1. 当iPhoneXR 升级 卡死在白苹果读条界面,已解决
  2. vue+elementui封装下载base64文件流,下载模板。
  3. 零配置网络助力httpS的部署
  4. VMware安装华为存储模拟器
  5. 鞍山市电子计算机学校,鞍山市信息工程学校
  6. 因缺失增量信息而导致recoverseg恢复失败的情况
  7. 【黑马课程笔记】webAPI
  8. 方法----解决win10笔记本电脑连接电源无法休眠只是黑屏,使用电池可以正常休眠。
  9. 《财报就像一本故事书》刘顺仁(一) 山西出版集团山西人民出版社
  10. 基于51单片机的电梯控制器