Linux内核详解(三)

Linux中断处理

中断使硬件发出通知给cpu,cpu接收到中断后即停止当前工作并立刻向操作系统告知此信号的到来(中断控制器连接着多路中断管线,当接收到一个中断后,中断控制器便向cpu发送一个电信号)。

硬件设备生成中断并不考虑与处理器的时钟同步——中断随时可以产生,内核随时被中断。不同的设备对应不同的中断,每个中断都有一个唯一的数字标志,这样操作系统就可以给不同的中断提供对应的中断处理程序。


在操作系统中,异常不同于中断,异常产生必须考虑与处理器时钟同步(也称同步中断),比如cpu执行到错误指令、通过软中断实现系统调用以及发生内存缺页等(由软件引起的),必须由内核来处理时,cpu就会产生一个异常。


内核响应一个中断是通过一个名为中断处理程序的函数。产生中断的每个设备都有一个相应的中断处理程序(但通常不是和特定设备关联,而是和特定中断关联,即如果一个设备可以产生多种不同的中断,那么该设备就可以对应多个中断处理程序,相应的该设备驱动程序也就需要准备多个这样的函数),一个设备的中断处理程序是其设备驱动程序的一部分——设备驱动程序是用于对设备进行管理的内核代码。


一般把中断处理流程分为两部分:上半部和下半部。上半部是中断处理程序——接收到一个中断后立即开始执行,但只做有严格时限的工作;下半部则执行能够被允许稍后完成的工作。以网卡为例,当网卡接收到来自网络的数据包时,需要通知内核数据报到达,因此网卡立即发出中断,内核执行网卡已注册的中断处理程序,中断开始执行,通知硬件拷贝最新数据包到内存——这些都有需要快速完成而又与硬件相关的工作,内核也需要快速拷贝数据包到内存中(因为接收缓冲区大小有限),避免网卡/内核缓存溢出。当数据包被拷贝到系统内存后,中断即将控制权交还给之前的程序,处理数据的其他工作在随后的下半部中进行。


另外在Linux中,中断处理程序不是可重入的。


当执行一个中断处理程序时,内核就处于中断上下文,相对于进程上下文(执行系统调用/内核线程),内核代表进程执行,进程上下文可以休眠或者调用调度程序,而中断上下文则与进程没有任何关系,因此中断上下文不能休眠(也就不能再中断处理程序中调用睡眠阻塞函数)。


Linux处理下半部

中断处理程序只能完成中断处理流程的上半部。在最理想的情况下,最好是中断处理程序将所有工作都交给下半部执行,这样中断处理程序能够尽快地返回——取决于驱动程序开发者自己判断。


中断处理程序会异步执行,并且在最好的情况下也会锁定当前的中断线,所以中断处理程序执行越快越好:

  • 如果一个任务对时间非常敏感,则将其放到中断处理程序中执行;
  • 如果一个任务和硬件相关,则将其放到中断处理程序中执行;
  • 如果一个任务确保不会被其他中断打断,则将其放到中断处理程序中执行;
  • 其他所有任务考虑放到下半部中执行。


下半部的执行没有明确的时间,通常在中断处理程序一返回就马上执行。下半部的关键在于当它们运行时允许响应所有中断。此外,和上半部只能通过中断处理程序实现不同,下半部可以通过多种机制实现。

下半部的实现:

  • 最早的Linux使用 bottom half(BH)来实现下半部——上半部通过一个32位整数中的一位标识执行哪个BH,并且每个BH都在全局范围内进行同步。
  • 基于工作队列——定义一组队列,其中每个队列都包含一个由等待调用的函数组成的链表,这些函数根据其在队列的位置在某个时刻会被执行,驱动程序将它们自己的下半部注册到合适的队列中。
  • 基于软中断和tasklet ——软中断是一组静态定义的下半部接口 ,可以在所有处理器上同时执行;tasklet是基于软中断实现,不同类型的tasklet可以在不同处理器上同时执行,但相同类型的tasklet不能同时执行。(对于大部分下半部处理来说tasklet就足够了,像网络这样对性能要求非常高才会使用软中断)
  • 内核定时器——将操作推迟到某个确定时间之后执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值