xiufeigo™
Home
Linux 性能瓶颈排查
Linux 软中断

一、中断是什么

中断是一种异步的事件处理机制,可以有效的提高系统的并发处理能力。

可以举一个例子,比如你在外卖平台定了一份外卖,但是这个平台并没有预估送达时间,而且配送员送到了也不会敲门按门铃,到了如果没人拿他就直接跑了。所以你只能苦苦的坐在门口等待外卖员上门,直到拿到你的外卖。这种形式就叫做不可中断状态,因为你在等外卖的时候不能做其他事情。

但是如果你的外卖平台具有实时进度提醒,且外卖员送达后会电话联系你出来拿外卖。那么你就可以下单后去做其他的事,直到电话响了你再接电话、取外卖就行了。在这里,打电话就是一个中断,在没收到电话的时候你持续做另一件事,直到接到电话(发生中断)才执行其他动作——取外卖。

由于中断处理程序会打断其他程序的运行,所以为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行。如果中断本身要做的事情不多,那么处理起来也不会有太大的问题;但如果中断本身要处理的事情太多,中断服务程序就有可能要运行很长时间。

特别是中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断程序都不能响应,也就是说中断可能会丢失。

还是以外卖为例,这次你下单了两份外卖,一份炸鸡跟一份奶茶,并且是由两个外卖小哥配送,同时他们到了之后又都会给你打电话通知外卖送达。但这次,你的奶茶送到时,由于配送出了问题导致奶茶破损,于是你在电话里头跟外卖小哥沟通售后/赔偿事宜沟通了很久。于此同时你的炸鸡也到了,但是你的电话在跟奶茶的外卖小哥沟通导致了电话占线(系统关闭了中断响应),导致炸鸡的外卖小哥无法联系上你,于是他可能试了几次就走掉了(中断丢失)。

二、软中断

如果你弄清了上面的“取外卖”模式,那对系统的中断机制就很容易理解了。事实上,为了解决中断处理程序执行过长导致中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:

  • 上半部用来处理快速中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作。

  • 下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行

还是“炸鸡与奶茶”的例子,上半部就是你接电话,告诉外卖小哥你已经知道了,晚点你上外卖平台申请理赔就行了,然后电话就挂了;下半部才是在外卖平台申请理赔等动作。这样,第一个外卖小哥不会占用你太多时间,当第二个外卖小哥到了的时候,照样能打通你的电话。

所以,这两个阶段也能这么理解:

  • 上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行

  • 下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行

三、查看软中断和内核线程

可以通过 proc 文件系统来查看捏合数据结构,其中

  • /proc/softirqs 提供软中断的运行情况

  • /proc/interrupts 提供硬中断的运行情况

/proc/softirqs 文件示例

$  cat /proc/softirqs
                    CPU0       CPU1
          HI:          1          0
       TIMER:   78492795   69611989
      NET_TX:          0          1
      NET_RX:    3359701    3080468
       BLOCK:    3842791          0
BLOCK_IOPOLL:          0          0
     TASKLET:         16          0
       SCHED:   27857273   29745084
     HRTIMER:          0          0
         RCU:   42876951   37899812

注意点

  1. 软中断类型:也就是这个界面的第一列的内容,从第一列可以看到软中断分为 10 种类型

  2. 同一种中断在不同 CPU 上的分布情况:正常情况下,同一种中断在不同 CPU 上的累计次数应该差不多

  3. TASKLET 在不同 CPU 上的分布不均匀:TASKLET 是最常用的软中断实现机制,每个 TASKLET 只运行一次就会结束,且只在调用它函数所在的 CPU 上运行,因此 TASKLET 非常简便。不过也会存在一些问题,比如只在一个 CPU 上运行导致调度不均匀,或不能在多个 CPU 上并行运行带来的性能限制

查看软中断线程,可以通过查找编号为 ksoftirqd/CPU 的进程,比如下面指令:

$ ps -aux | grep softirq
root         6  0.0  0.0      0     0 ?        S    Apr06   0:01 [ksoftirqd/0]
root        14  0.0  0.0      0     0 ?        S    Apr06   0:01 [ksoftirqd/1]
root     12720  0.0  0.0 112816   980 pts/6    S+   22:59   0:00 grep --color=auto softirq

注意,这些线程的名字外面都有中括号的,这说明 ps 无法获取他们的命令行参数(cmdline)。一般来说,ps 的输出汇总,名字在中括号里的,一般都是内核线程。

四、软中断升高会发生什么

一般情况下,软中断升高在 top 中不容易发现,但给人的感觉是 shell 反应很迟缓,敲下回车都会卡一会。观察软中断升高速率可以使用 watch 来观察,之后再对症下药即可。

watch -d cat /proc/softirqs
                    CPU0       CPU1
          HI:          1          0
       TIMER:   78516628   69634209
      NET_TX:          0          1
      NET_RX:    3360907    3081073
       BLOCK:    3843820          0
BLOCK_IOPOLL:          0          0
     TASKLET:         16          0
       SCHED:   27866184   29754814
     HRTIMER:          0          0
         RCU:   42890013   37911964

小结

Linux 中的中断处理程序分为上半部和下半部:

  • 上半部对应硬件中断,用来快速处理中断

  • 下半部对应软中断,用来异步处理上半部未完成的工作

Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类型,可以通过查看 /proc/softirqs 来观察软中断的运行情况。

粤ICP备2022009857号-1