一、中断的魅力
1、中断在生活的魅力
比如你订了一份外卖,但是不确定外卖什么时候送到,也没有别的方法了解外卖的进度,但是,配送员送外卖是不等人的,
到了你这儿没人取的话,就直接走人了。所以你指能苦苦等着,时不时去门口看看外卖送到没,而不能干其他事情。
不过呢,如果你在订外卖的时候,你就跟配送员约定好,让他送到后给你打个电话,你就不用苦苦等待了,就可以去忙别的事情,
直到电话一响,接电话、取外卖就可以了
这里的"打电话",其实就是一个中断。没接到电话的时候,你可以做其他的事情;只有接到了电话(也就是发生中断),你才要进行另一个动作:取外卖
这个例子你就可以发现,中断其实就是一种异步的事件处理机制,可以提高系统的并发处理能力
2、什么是中断?
中断其实就是一种异步的事件处理机制,可以提高系统的并发处理能力
3、为什么要有中断呢?
可以提高系统的并发处理能力
二、中断的丢失
1、中断为什么会丢失
1、由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序需要尽可能快的运行
2、如果中断本身做的事情不多,那么处理起来也不会又太大问题
3、但如果中断要处理的事情很多,中断服务程序就可能要运行很长时间
特别是,中断处理程序在响应中断时,还会临时关闭中断,这就会导致上一次中断处理完成之前,其他中断不能响应,也即是说中断有可能会丢失
2、通过以取外卖理解中断丢失
1、假如你定了2分外卖,一份主食和一份饮料,并且是由2个不同的配送员来配送。
2、两份外卖都约定了电话取外卖的方式,但是问题又来了
3、当第一份外卖送到的,配送员给你打了个长长的电话,商量发票的处理方式,
4、与此同时,第二个配送员也到了,也想给你打电话,但是很明显,因为电话占线(也就是关闭了中断响应)
5、第二个配送员的电话是打不通的。所以,第二个配送员很可能试了几次后就走掉了(也就是丢失了一次中断)
三、如何解决中断的丢失问题
1、linux 将中断处理过程分成几个阶段分别是什么?
1、linux 将中断处理过程分成两个阶段
2、分别是上半部用来快速处理中断和下半部分用来延迟处理上半部分未完成的工作
3、上半部用来快速处理中断:它在中断禁止模式下运行,只要处理跟硬件紧密相关的时间敏感的工作
4、下半部分用来延迟处理上半部分未完成的工作:通常一内核线程的方式运行
2、通过取外卖理解上半部和下半部
上半部就是你接电话,告诉配送员你已经知道了,其他事儿见面再说,然后电话就可以挂断了;
下半部才是取外卖的动作,以及见面后商量发票处理的动作
这样第一个配送员不会占用你太多时间,当第二个配送员过来时,照样能正常打通你的电话,
3、通过网卡接收数据包理解上半部和下半部
网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了,这时,内核就应该调用中断处理程序来
响应它,你可以自己先想一下,这种情况下的上半部分和下半部分分别负责什么工作呢?
对上半部来说:
既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(标识数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理
而下半部
被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。
所以,这两个阶段你可以这样理解:
上半部分直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行
而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行
实际上,上半部会打断cpu正在执行的任务,然后立即执行中断处理程序,而下半部以内核线程的方式执行,并且每个cpu都对应一个软中断
内核线程,名字为"ksoftirqd/cpu 编号" 比如0号cpu对应的软中断内核线程的名字就是ksoftirqd/0
注意事项:
软中断不只包括了刚刚所讲的硬件设备中断处理程序的下半部。一些内核自定义的时间也属于软中断,比如内核调度和rcu锁
(read-copy update 的缩写,rcu 是 linux 内核中最常用的锁之一)等。
四、查看软中断和内核线程
1、查看软中断
ubuntu 18.04
[root@localhost ~]# cat /proc/softirqs cpu0 cpu1 cpu2 cpu3 hi: 3 1 0 0 timer: 25265822 43447443 10082461 12874428 net_tx: 387749 5 1927 1 net_rx: 28946864 41272 32597 23383 block: 888 539 1296 1162217 block_iopoll: 0 0 0 0 tasklet: 39231 9 110 1 sched: 21957135 40794916 7650486 10479809 hrtimer: 0 0 0 0 rcu: 2925240 2746051 2401640 2383562
centos
[root@luoahong ~]# cat /proc/softirqs cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 cpu6 cpu7 cpu8 cpu9 cpu10 cpu11 cpu12 cpu13 cpu14 cpu15 cpu16 cpu17 cpu18 cpu19 cpu20 cpu21 cpu22 cpu23 cpu24 cpu25 cpu26 cpu27 cpu28 cpu29 cpu30 cpu31 cpu32 cpu33 cpu34 cpu35 cpu36 cpu37 cpu38 cpu39 cpu40cpu41 cpu42 cpu43 cpu44 cpu45 cpu46 cpu47 cpu48 cpu49 cpu50 cpu51 cpu52 cpu53 cpu54 cpu55 cpu56 cpu57 cpu58 cpu59 cpu60 cpu61 cpu62 cpu63 cpu64 cpu65 cpu66 cpu67 cpu68 cpu69 cpu70 cpu71 cpu72 cpu73 cpu74 cpu75 cpu76 cpu77 cpu78 cpu79 cpu80 cpu81 cpu82 cpu83 cpu84 cpu85 cpu86 cpu87 cpu88 cpu89 cpu90 cpu91 cpu92 cpu93 cpu94 cpu95 cpu96 cpu97 cpu98 cpu99 cpu100 cpu101 cpu102 cpu103 cpu104 cpu105 cpu106 cpu107 cpu108 cpu109 cpu110 cpu111 cpu112 cpu113 cpu114 cpu115 cpu116 cpu117 cpu118 cpu119 cpu120 cpu121 cpu122 cpu123 cpu124 cpu125 cpu126 cpu127 hi: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 timer: 4699549 4940977 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 net_tx: 4267 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 net_rx: 605 102597 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 block: 4595883 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 block_iopoll: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 tasklet: 56 1014 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sched: 418267 475421 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 hrtimer: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 rcu: 389674 288935 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2、软中断文件注意事项
1、不过你可能发现,tasklet在不同cpu上的分布并不均匀,tasklet是最常用的软中断实现机制,每tasklet个只运行一次就会结束,并且只在调用它的函数所在的cpu上运行。
因为使用tasklet特别简便,当然也会存在一些问题,比如说由于只在一个cpu上运行导致调度不均衡,再比如因为不能在多个cpu上并行运行带来了性能限制
2、另外,刚刚提到过,软中断实际上是以内核线程的方式运行的,每个cpu都对应一个软中断内核线程,这个软中断内核线程叫做ksoftirqd/cpu 编号。那要怎么查看这些线程的运行呢?
[root@luoahong ~]# ps aux | grep softirq
root 3 0.2 0.0 0 0 ? s 11:09 0:43 [ksoftirqd/0]
root 14 0.0 0.0 0 0 ? s 11:09 0:08 [ksoftirqd/1]
root 19903 0.0 0.0 112712 976 pts/0 r 17:04 0:00 grep --color=auto softirq
注意:这些线程的名字外面都有中括号,这说明ps无法获取他们的命令行参数(cmline)。一般来说,ps 的输出中,名字括在中括号里的,一般都是内核线程