Day 27:IRQ (Part 1) - 断开魂结!

简介

中断这个机制因为 busy waiting 的等待很浪费处理器的资源,所以会希望有一个机制可以做到类似「到货通知」的效果。

大原则:有人插队 = 有人要等更久

因为 interrupt 是一件「停下目前执行流程,转而处理其他事情」的执行过程,这表示 原先的工作会被延後,但是又不得不给 interrupt 「插队」。无论如何要记住:当得到一段「可以插队」的时间时,这是以其他执行单元的延迟换取的,所以最好这个插队的时间不要拖太久。才不会拖到其他事情。因此,概念上来说,会把一个中断要执行的任务,分成两个部分:

  1. 那些希望利用「插队时间」处理的部分,也称为「上半部」(top-half)
  2. 不用现在立刻处理的部分,也就是「下半部」(bottom-half)。

上半部:尽量不拖延

上半部是插队换来的时间,而且因为无法预期 interrupt 什麽时候会发生,所以这种「插队」可以说是突发状况。为了避免突发状况让本来预定的工作延迟太久,所以应变要能快就快。

这时候会做的事通常是厘清有什麽事情要处理,然後把工作交给适当的执行单元执行。比如交给 Workqueuetasklet 等等可以更有效率安排与执行工作的机制来代为执行。这类「可以把工作推给他们」的机制,通称 work deferring mechanismWorkqueuetaskletsoftirq 等等都可以帮忙执行。虽然是稍微久远的资料,但这里面有简单介绍各种这样的机制。

而那些「交给这些延迟执行的机制」部分的工作,就称为「下半部」。

下半部:剩下的就是下半部的事了

这就是指 interrupt 发生之後,那些「请其他执行单元代为执行」的工作。这些机制有的也是另外一种 interrupt; 有的则是另外一个行程。这两种不同的执行状态

两种 Context:Interrupt 与 Process

Interrupt:实实在在的 ISR

中断发生时会跳到某些预先定义好的函式的进入点。这些函式称作 interrupt service routine。他们存在特定的中断向量表之中,一旦被触发,处理器就要模式切换过去服侍处理它。以 Cortex-M 为例,这些 interrupt service routines 的进入点,就是下面对应的中断向量。执行中断的意思,就是跳转到那些中断向量中执行

Process:人为的抽象结构

相较於 interrupt 这种在硬体中有特殊地位的执行方式,process 的概念是人为定义的,本质是作业系统设计者定义的,「一个可以描述工作进度的资料结构」。比如说:你觉得一个工作的进度,可以用 9 个暂存器加上 program counterlink register 描述,那这就可以拿来当一个抽象化的行程。

像是在 (空一格) 这个例子 中,一个行程只是一组 {r4, r5, r6, r7, r8, r9, r10, r11, ip, lr} 暂存器形成的有序对。对於多个这样的有序对所代表的任务,你可以:

  1. 把现在这一组有序对的数值存到记忆体中。
  2. 接着载入另外一组这样的有序对到处理器中。
  3. 让处理器开始执行这新的一组有序对所代表的工作进度。

Boom! 你完成 context switch 了!处理器轮流在多个代表任务的资料结构进行替换,就制造了「多个行程在执行」的~~假象~~抽象化

而用来描述工作进度与执行状态的资料结构,不仅限於是一组暂存器形成的有序对,也可以是一个复杂的资料结构。像是 Linux 中的 struct task_struct。行程就是很多这种而形成的假象抽象化。

但最终,这些「行程」是人为设计出来的东西,就是一组用以描述与恢复工作进度的 metadata 。不管这组 metadata 的形式是特定几个暂存器的数值,或是其他特别的资料结构,处理器把这些特定形式的 metadata 轮流拿起来看一看,把他们上面描述的工作进度做一点点,然後丢到旁边换下一个。轮流在这个抽象的工作进度之间不断切换执行,就是人所看到的「行程正在往下执行」

两种 Context

从上面的例子可以知道:process 的执行,是处理器在不同代表「任务进度」的资料结构间,不断切换执行,形成的~~假象~~抽象化; 而 interrupt 的执行则无关乎这样的抽象化存不存在。这就造就了两种不同的 context:前者执行时仰赖行程这个抽象化的设计,但後者不用。

有时候会有以 current 巨集作为两者的指标。比如说文件中 Unreliable Guide To Hacking The Linux Kernel 的章节就有提到。

补充:Threaded IRQ

虽然说看起来 interrupt 的工作就是在 interrupt context 执行; 而行程就是在 process context 执行。但 Linux 也有把 interrput 移往 process context 处理的机制,称作 threaded IRQ。这是为了 PREEMPT_RT 设计的机制:这样中断的执行就可以像行程一样被抢占与排程。

按:虽然说就算没有 threaded IRQ,有的处理器 (比如说 Cortex-M 的 NVIC 有优先权高低的机制) 也可以使中断被其他中断抢占。但我想不到把所有内容编排在一起的合适写法。

术语:Atomic Context

「执行时没有人可以打断他」的执行状态,称作 atomic context。与之对立的就是 non-atomic context,比如说像行程,他可以被排程,或是「执行尚未结束时,有人可以把他送去等待或睡眠」,这种中断的状况,就不是 atomic context。这时候如果去休眠,没有机制可以改变他的执行状态,所以这会决定这个里面能做什麽事 (比如说:能不能持有会导致休眠的锁)。可以参考 LWN 的文章。

听起来有点像 interrupt context,但其实要考虑这个核心有没有 threaded IRQ 的机制。所以就把他放在最後面才提出来。


<<:  Day 27 Explore monitoring and reporting

>>:  [Day 27] 损失视觉化 Loss Visualization

Day 4 : HTML – 别动!你就停在那里!CSS position定位属性是什麽?

这里想和大家介绍一下CSS position到底是什麽 以防大家和我一样干了蠢事 (详情可看Day ...

day3 让我看看,什麽是Coroutine Scope

我想大家看到前一天的范例,应该会有这种感觉吧 唉呦,很猛嘛~ [coroutine]对呀,我超厉害的...

Day21输出(JavaScript)

JS没有print或者输出这类的函数 但是有以下这四种方法可以捞出它输出的资料哦 这些示范只用到小量...

Angular-介绍(Day14)

好的,在我们结束Spring Boot API的架设後,再来我们要开始进入前端框架-Angular的...

Cobol Picture Clause/cobol field type

常看到,却老搞不清楚,这次很幸运,google到说明与live demo. Cobol Pictur...