中断、软中断、抢占和多处理器

内核代码中大家经常会看到这么些函数:

  • spin_lock_irq()

  • disable_

说起来大家好像都知道,这些函数的作用就是关中断,关抢占,拿锁。那请问,为什么要真么做?如果不这么做会发生什么呢?

可能你会觉得这个问题很low,以前我也觉得这不是明摆着的么?但是仔细一想这背后的原理,感觉自己还真说不清楚。

今天我终于有点get到了。看了别人的很多文章,想用自己的语言组织一下。

产生“并行”的两大原因

总的来说上述的这些函数的目标都是为了使程序在当前计算机系统上能够并行执行。那么产生这些并行执行的原因都有哪些?

我总结下来有两点:

  • 广义抢占

  • 多处理器

广义抢占不仅仅是内核中说的抢占,而是指任何能够打断当前处理器执行顺序的。现有的中断、软中断和抢占都是一种抢占的机制。

在这些机制下,处理器的执行顺序会被打断。比如当中断到来,当前处理器就要收拾好现场,去处理中断。而进程调度也是一种“抢占”,因为进程运行的环境会被切换,当下次再执行时别人已经执行过了。只不过这个行为主要影响的是进程内部。如果是一个单线程进程,那么即使被打断,我们也知道没有别人会动它的环境。而对多线程进程来说,我们就要用锁等机制来保护共享资源了。

这样也就引出了第二个抢占的来源--多处理器。和多线程原理一样,如果系统中只有一个处理器,那么即使CPU运行环境被打断,我们也能保证共享资源不会有别人改动,那就不需要采用什么保护机制。但是如果有多处理器,那就可能有多处理器共同访问共享资源的情况发生。此时我们就需要用锁等机制来保护共享资源。

好了,叨叨了半天,也不知道有没有把这部分梳理清楚。

所以总的来说这么多函数的目的其实只有一个:

在这么一个纷繁复杂,弱肉强食的计算机系统中,如何采用正确的互斥原语来保护一个共享变量不会被同时修改。

不采取任何措施,程序一定会崩。如果都放大招,那程序的性能就一定会有影响。

各种抢占之间的不同之处

刚才我们看到了广义抢占的种类,那各种抢占之间有没有什么差别呢? 有的,暂时想到的是有两个方面的差异:

  • 优先级

  • 是否能睡眠

先来看看优先级,优先级从高到底,意味着高优先级可以抢占低优先级。

中断 -> 软中断 -> 抢占

也就是软中断在执行时可以被中断打断。

当然我觉得这个优先级有些是硬件定义的,比如中断优先级最高。而有些则是软件定义的。比如中断过程中不能执行软中断,这是在代码中有保护的。

而第二点不同,是否能够睡眠则影响到了在保护共享资源时,可以采用什么锁。

所以总结来看,这两点的差异本别给出编程上的指导是:

  • 优先级: 决定如何正确关中断,关软中断,关抢占

  • 是否能睡眠: 决定采用什么锁

了解了各种抢占及他们之间的区别后,我们来看看针对各自的情况应该如何做到保护。

多处理器之间的保护

多处理器之间的保护可以参考多线程之间的保护,主要就是采用各种锁来保护共享资源。

但是需要注意一点,在不同抢占形式中可以使用的锁是有限制的。比如在中断、软中断中不能用会休眠的锁。

抢占之间的保护

各抢占之间的保护主要是避免自己被更高优先级的抢占而抢占。

比如软中断的优先级没有中断高,那么在需要处理某些共享资源时,需要关中断不让中断来打断自己的工作,否则将会产生死锁。

Last updated