中断处理的两个阶段

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)

以上是关于中断处理的两个阶段的主要内容,如果未能解决你的问题,请参考以下文章

S5PV210的中断处理机制详解

S5PV210的中断处理机制详解

Linux 中断处理浅析

用户态内核态

当另一个类完成处理所需数据时如何中断 Viewcontroller

linux驱动之中断处理过程C程序部分