日更,今天聊一个技术问题:操作系统的中断。
中断是啥:从订外卖说起
首先,这里声明一下,以下比喻并非我原创,摘自极客时间我购买的专栏《Linux性能优化实战》,我略有扩充。
假如你订了份外卖,没有任何方法获取外卖员何时会过来(就好像原始社会),且外卖员不会等你,到达后看到门口没有人就会离开。这时候你就只能不停地去门口查看,不能做其他事情。你会不会很崩溃😃?
后来你想了个办法,下单时跟配送员约好,他到了就打电话给你。那么你就可以去忙别的事情,直到电话一响,去取就是了。
非常容易理解吧?那么你能猜出来上面的例子中,哪部分对应的是中断吗?是的,就是接电话和取外卖。假如你正在写文章,电话一响,你就被打断了。
Linux中的中断定义就是:中断是系统用来响应硬件设备请求的一种机制,它会打断正常进程的调度,转而调用内核中的中断处理程序来响应硬件设备的请求。
为啥要有中断
因为有了电话约定,你就不必苦苦等待,可以做很多其他事情,例如写文章啦、打游戏啦、陪亲人啦都可以。毫无疑问,这会让你在相同的时间里做更多的事情。对应到操作系统,中断作为一种异步事件处理机制,可以让CPU抽出身来处理其他工作,从而极大提高并发处理能力。
这是现代多任务操作系统的一个最重要的特点。
Linux的中断特点
现在你知道了,中断会打断你手中的事情,例如你正在写作,电话一响,你就必须去取外卖。如果你足够细心,你会发现一个问题,例如:
我脑海中的灵感正如泉涌,如果取外卖花了我太长时间(例如配送员被小区保安拦住不让进,我要跑到大门口去取),那么这个体验岂不是很糟糕?
为了应对这种花费太多时间较差的情况,你想到了让外卖小哥先放到保安室,然后他可以自行离开。你也可以不必着急去取,写完文章再去取也不迟是吧?
Linux为了处理这种情况,当然也考虑到了这点。Linux把中断分成了两个阶段:上半部和下半部。
- 上半部:接电话。快速处理,在屏蔽其他中断模式下运行(可以理解为你正在打电话,其他人再打就会占线打不通,被屏蔽),主要处理跟硬件相关或时间敏感的工作。
- 下半部:去取外卖。通常是交由内核线程去运行,主要处理上半部分未完成的工作。这部分会被放到工作队列里异步执行。
如果你熟悉多线程编程,就很容易理解了,上半部分是临界区(某一时刻只能有一个线程据有),下半部分则比较自由了,可以并行,可以异步等等。
那么,硬中断和软中断都是什么鬼?中断服务程序呢?
上面知道了上半部和下半部之后,其实可以粗略地理解为:上半部=硬中断;下半部=软中断。
硬中断 | 上半部,硬件设备的中断,快速处理,通常很短. |
---|---|
软中断 | 下半部,或一些内核自定义事件(如网络收发,定时,调度,RCU锁),内核线程执行. |
中断服务程序就是中断一旦发生,就会去执行的代码块。软硬中断都会有各自的中断服务程序。它们的特点是比较简短(尤其硬中断,屏蔽模式可能导致其他中断丢失)。
中断和CPU使用率关系
�我们使用top命令,第一行输出:
$ top
%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
...(省略)...
第一行显示的就是CPU使用率,我们知道:
CPU总使用率
= 除idle(id)之外的所有使用率之和
= us + sy + ni + wa + hi + si +st
其中hi
表示硬中断(hardware interrupts),si
表示软中断(software interrupts)。
所以,如果hi
和si
升高,也必然会导致CPU使用率升高哟。反向推理也很容易理解,中断就意味着切换,切换就意味着开销,所以中断肯定是有负载的。
查看linux下的软硬中断种类及发生的次数,可以查看:
-
/proc/interrupts
提供了开机以来硬中断的运行情况; -
/proc/softirqs
提供了开机以来软中断的运行情况.
例如查看软中断:
$ cat /proc/softirqs
CPU0 CPU1
HI: 0 0
TIMER: 811613 1972736
NET_TX: 49 7
NET_RX: 1136736 1506885
BLOCK: 0 0
IRQ_POLL: 0 0
TASKLET: 304787 3691
SCHED: 689718 1897539
HRTIMER: 0 0
RCU: 1330771 1354737
- 第一列展示的是软中断的类型,共10个,如
NET_RX
表示网络接收中断;NET_TX
表示网络发送中断;RCU
表示Read-Copy Update缩写,是linux中最常用的锁之一. - 第二列及以后的表示在每个CPU上的分布.通常,同一种中断在不同CPU上的累计次数应该差不多,都在同一个数量级上.除了
TASKLET
.
什么是
TASKLET
:最常用的软中断的一种实现,简单易用,每个TASKLET
只运行一次就会结束,并且只在它的函数所在的CPU上运行.这意味着,这种轻量级中断会导致调度不均衡,会导致在多个CPU上并行带来性能限制.
再来一个更常用的例子:网卡接收数据
- 上半部:网卡接收到数据包时,会通过硬件中断来通知内核有新的数据到了.此时内核就调用中断处理程序来响应它:把网卡的数据读取到内存中,然后更新一下寄存器状态(表示数据已经读完),然后再发送软中断,进入下半部.
- 下半部:(某一时刻)下半部信号被唤醒,则从内存中取到数据,按照协议栈逐层解析和处理,最后送给应用程序,中断完毕.
划重点:总结
- 中断是系统用来响应硬件设备请求的一种机制,它会打断正常进程,转而调用内核中的中断处理程序来响应硬件设备的请求。
- 中断是一种异步的事件处理机制,提高系统并发能力。
- linux把中断分为两部分:上半部=硬中断,下半部=软中断。硬中断会开启屏蔽模式,所以大都简短以尽快结束;软中断可以异步(延迟)执行,自由度较大。
- 如果你的CPU升高,要看看是不是中断引起的,如果是,看看是什么类型中断,然后找出制造这种中断的罪魁祸首(进程)。
网友评论