从中断说起
这周电面了阿里中间件,结果对方让我解释下什么是中断,我有点懵了,只记得外设发出的指令会造成中断,让系统处理。
然后又让我从网卡层面解释下中断,记得当初教科书没说过这茬。。
不过面完后,联想了一下,网卡也是外设,进来的数据包,不发指令,谁去处理?那么发了指令,那就是中断指令了。
那么这貌似和epoll 还有些关联。
epoll 为什么快,因为不像select 需要对所有的连接遍历下check下有没有数据(是 On 的操作), 而是直接就知道哪些 连接有数据(.select() 是 O1 的操作), 那么是如何做到的呢(事件源)?
之前没想过,现在知道了,就是网卡发出中断的事件源。
理一下上面的流程(猜测):
- 网卡收到数据包, 发中断
- cpu 将数据包放到协议栈缓存+解析?
- 解出的 数据包就放到 TODORead 的queue?
以下浅浅的总结了下中断,copy from 深入理解linux内核, 以及网上别人的文章
中断
中断 有硬中断,软中断
硬中断相对来是被动接收到的中断, 硬件发出,软中断是程序产生的,人为发出的
硬中断
种类上说分两种,同步(异常)和异步(中断)
同步:指令执行后产生,也就是程序主动发出的,也就是异常,用于中断自己。。
异步:间隔定时器 和 IO 设备产生。 比如网卡收到数据包,敲键盘。。
中断到达时,cpu 会暂停当前做的事情,优先处理中断,实现方法:在内核态堆栈保存程序计数器的当前值(save 当前),并把与中断类型相关的一个地址放入程序计数器(强行插队)
软中断
软中断, tasklet
软中断: 程序产生,书上定义了6种,举个例子,将数据传给IO设备,比如 写硬盘,发数据包到网卡都是。
软中断中写硬盘,发数据到网卡这种IO操作优先级比较低,排在第4,5,所以是可以延迟执行的,延迟执行的方式是放到工作队列,异步之行
然后如果程序要用软中断那么内核对外提供了个好用的封装,就是 tasklet, 原理参考这里
从书上只能看出,比如网卡收到一个数据包就立即一次中断。不过发现事实上并不是这样。
从知乎上看到这个答案, 网卡并不是真的一个数据包就一个中断, 在高并发下会帮你做点和合并操作
从kernel层面将,事件产生有可能不是由硬件中断触发的,在一定情况下kernel的确会轮询,因为响应硬件中断是一个成本比较高的操作。
以网卡为例,当数据量很少的时候,每来一个数据包网卡都回产生一个中断,kernel响应这个中断,从网卡缓冲区中读出数据放进协议栈处理,当满足一定条件时,kernel回调用户代码,这里的“回调”一般情况下是指从一个kernel syscall中返回(在此之前用户代码一直处于block状态)。
当数据量很大时,每个包都产生一个中断就划不来了,此时kernel可以启动interrupt coalescing机制,让网卡做中断合并,也就是说来足够多的数据包或者等待一个timeout才会产生一个中断,kernel在响应中断时会把所有数据一起读出来处理,这样可以有效的降低中断次数。
当数据量更大时,网卡缓冲区里几乎总是有未处理的数据,此时kernel干脆会禁掉网卡的中断,切换到轮询处理的模式,说白了就是跑一个忙循环不停地读网卡缓冲区里的数据,这样综合开销更低。
再现代操作系统上说,其实这个模块就是 DMA (Direct Memory Access), 只不过书上是磁盘的,其实网卡也一样,网上有篇文章说了这个,和上面答案类似
顺便再复习下 epoll 的 水平触发,边缘触发, 详细可以看 这里, 感觉和本文关系不大
总结下感觉,中断就是中断,和epoll应该并没有直接的关联,它应该只关联到协议栈,然后,epoll select 应该是再协议栈之上的对外封装。
TODO 验证。。
reference
http://www.kryptosx.info/archives/1190.html
https://www.zhihu.com/question/20122137
http://rock3.info/blog/2013/11/22/tasklet%E5%8E%9F%E7%90%86/
http://www.cnblogs.com/yuuyuu/p/5103744.html
https://www.zhihu.com/question/20502870
http://blog.chinaunix.net/uid-24148050-id-1667017.html
http://www.cnblogs.com/gogly/archive/2012/06/10/2541573.html