什么软中断
一、引言
本文参考 小林coding 的《图解操作系统》,也是我十分喜欢的一个公众号博主,为他打 call
老读者知道我之前再写 Kafka
的博文,为什么突然开始写操作系统的呢?
原因在于:当我看到 Kafka
服务端的一些 IO 操作时,我发现我看不懂了,了解之后发现这里 Netty
的概念。
当我尝试了解 IO 时,我发现一些内存、磁盘的交换,搞的我焦头烂额,于是,想静下心来从头开始。
当我把 小林coding 的 《图解操作系统》看完之后,我发现对操作系统的理解更上一层楼。
用一段话,作为今天的开场白:
读书的根本目的,未必是解决现实问题,它更像一场心灵的抚慰。
一个喜欢读书的人,可能不会记得自己读过哪些书。
但是那些看过的故事、收获的感悟、浸染过的气质,就像一颗种子,会在你的身体里慢慢发芽长大,不断提升你的认知,打开你的视野。
一、中断是什么
在计算机里面,中断是系统用来响应硬件设备请求的一种机制,操作系统收到硬件的中断请求,会打断正在执行的线程,然后调用内核的中断处理程序来相应请求。
简单举个外卖的例子:当我点了一份炸鸡外卖后,我就去打游戏去了。等到外卖到了,外卖员给我打电话,我再停止打游戏去拿外卖。
这里的打电话,对应计算机的中断,当接到电话时,会停止当前的事情去做另一件。
从上述例子我们可以看到:
中断是一种异步的事件处理机制,可以提高系统的并发处理能力。中断请求的响应程序,也就是中断处理程序,要尽可能快的执行完,这样可以减少对正常进程运行调用的影响。
这里还存在一个临时关闭中断 的问题。如果当前的中断处理程序没有执行完之前,系统中的其他中断请求都没法被响应,也就是说中断有可能会丢失,所以中断处理程序要短且快。
二、什么是软中断
前面我们提到了中断处理要短且快,这样才能减少对正常进程运行调度的影响,而且如果当前的中断时间过长,还会产生 临时关闭中断 的问题。
我们的 Linux 系统 为了解决中断处理程序执行过长或中断丢失的问题,将中断过程分为了两个阶段,分别为【上半部分和下半部分】
- 上半部分用来处理中断:一般会暂时关闭中断请求,主要负责处理跟硬件紧密相关的事情
- 下半部分用来延迟处理上半部分未完成的工作:一般以 内核线程 的方式运行
举个例子:网卡接受网络包的例子
网卡收到网络包后, 会通过 硬件中断 通知内核有新的数据到了,于是内核就会调用对应的中断处理程序来响应事件,这个事件的处理也分为上半部分和下半部分。
上部分要做到快速处理,只需要将网卡的数据读到内存中,然后更新下硬件寄存器的状态。比如把状态更新为表示数据已经读到内存的状态值。
接着,内核会触发一个软中断,把一些处理比较耗时且复杂的事情,交给 软中断处理程序 去做,也就是中断的下半部,主要是从内存中找到网络数据,再按照网络协议栈,对网络层进行逐层解析和处理,最终把数据送给应用程序。
所以,中断处理程序的上半部分和下半部分可以理解为:
- 上半部分处理硬件请求,也就是硬中断,主要是负责执行耗时短的任务,特点是快速执行
- 下半部分由内核触发,也就是软中断,通常是耗时长的任务,特点是延迟执行
硬中断会打断CPU正在执行的任务,然后立即执行中断程序,而软中断以内核的方式执行,并且每一个CPU都有一个软中断内核线程,名字通常为【ksoftirqd/CPU编号】,比如 0 号 CPU 对应的软中断内核线程的名字是 ksoftirqd/0
三、系统中有哪些软中断
在 Linux 系统中,可以通过查看 /proc/softirqs
的内容来知晓 软中断 的运行情况。使用/proc/interrupts
的内容来知晓 硬中断 的运行情况。
比如,我使用 /proc/softirqs
查看软中断:
每一种 CPU 都有自己对应不同类型软中断的 累积运行次数
软中断的类型
- NET_RX:网络接受中断
- NET_TX:网络发送中断
- TIMER:定时中断
- RCU:RCU锁中断
- SCHED:内核调度中断
每一种中断在各个CPU的累积次数成均匀分布
系统的中断次数变化速率:使用 watch -d cat /proc/softirqs
查看中断次数的变化速率
我们使用 ps
命令查看软中断在各 CPU 里面的内核线程
四、如何定位软中断 CPU 使用率过高的问题
首先使用 top
查看:
上面黄色部分,也就是 si
,就是 CPU 在软中断上的使用率,每个 CPU 的使用率都不高。
另外,也可以看到 CPU 使用率最高的进程也是软中断 ksoftirqd
,因此可以认为此时系统的开销主要来源于软中断。
如果要知道是哪种软中断类型导致的,我们可以使用 watch -d cat /proc/softirqs
命令查看每个软中断类型的中断次数的变化速率。
五、总结
为了避免由于中断处理程序执行时间过长,而影响正常进程的调度,Linux 将中断处理程序分为上半部和下半部:
- 上半部,对应硬中断,由硬件触发中断,用来快速处理中断;
- 下半部,对应软中断,由内核触发中断,用来异步处理上半部未完成的工作;
- Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类型,可以通过查看
/proc/softirqs
来观察软中断的累计中断次数情况,如果要实时查看中断次数的变化率,可以使用watch -d cat /proc/softirqs
命令。
每一个 CPU 都有各自的软中断内核线程,我们还可以用 ps
命令来查看内核线程,一般名字在中括号里面到,都认为是内核线程。
如果在 top 命令发现,CPU 在软中断上的使用率比较高,而且 CPU 使用率最高的进程也是软中断 ksoftirqd
的时候,这种一般可以认为系统的开销被软中断占据了。