中断处理的两个阶段
Posted Li-Yongjun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中断处理的两个阶段相关的知识,希望对你有一定的参考价值。
中断带来的麻烦
如果关闭中断,操作系统就是一行行指令顺序执行,和普通应用程序一样;
一旦打开中断,操作系统的执行流就会被打断,去处理中断,然后再恢复原来的执行过程。
中断优先级
如果有多个外设同时产生中断,CPU 同时接收到了这些中断,操作系统该如何处理呢?
这个时候就会用到中断优先级。
中断嵌套
操作系统会区分来自不同外设的中断优先级,优先处理高优先级的中断。如果在处理低优先级中断的时候,来了高优先级中断,那么操作系统会暂停当前中断的处理,先去处理高优先级的中断,处理完后再回到被中断的低优先级中断处理函数继续执行。
看来中断也有上下文啊,中断上下文?
中断嵌套带来的性能问题该如何解决?
由于发生中断时,高优先级中断会导致低优先级中断得不到响应,因而会导致低优先级的中断响应速度变慢。
该如何解决这个问题呢?
一种常用的办法:将中断处理的过程分为两个阶段,确认阶段和处理阶段。
第一阶段(上半部)
Top Half:马上做。
也就是硬中断。也就是确认阶段。
- 保存寄存器、屏蔽中断
- 恢复寄存器、返回现场
因为中断被屏蔽,所以不要做太多事情(时间、空间),将中断请求放入队列(或设置 flag),将中断延迟处理。
第二阶段(下半部)
Bottom Half:延迟完成
提供可以推迟完成任务的机制
- softirq
- tasklet(建立在 softirq 之上)
- 工作队列
这些下半部机制都可以被中断。
softirq 不能执行 sleep(),因为它没有对应的线程上下文,无法参与调度(不理解,不是有 [ksoftirqd/x] 吗??)。因此,如果处理逻辑中存在阻塞操作,比如操作磁盘,就不能使用 softirq 了。为了解决这个问题,Linux 内核提出了工作队列的机制。
通过工作队列,将剩余的工作交由 [kthreadd] 执行(下半部工作)。由于内核线程具有自己的上下文,可以参与调度,所以执行过程中可以调用 sleep(),从而避免用户进程被饿死,是一种非常灵活的机制。
- 在内核空间创建 FIFO 队列
- 上半部负责 enqueur(fn, args),workqueue
- 内核线程负责 dequeue 并执行 fn(args)
以上是关于中断处理的两个阶段的主要内容,如果未能解决你的问题,请参考以下文章