我读到Linux内核是抢占式的,这与大多数Unix内核不同。那么,内核抢占到底意味着什么呢?
一些类比或示例将比纯理论解释更好。
抢占式只是多任务处理的一种范例。还有其他类似协作多任务处理。通过比较它们可以更好地理解。
想象一下抢占式多任务的简单视图。我们有两个用户任务,它们都一直在运行,而没有使用任何I / O或执行内核调用。这两个任务无需执行任何特殊操作即可在多任务操作系统上运行。内核通常基于计时器中断,只是简单地确定是时候暂停一项任务,让另一项任务运行了。有问题的任务完全不知道任何事情发生。
但是,大多数任务偶尔会通过syscall发出内核请求。发生这种情况时,存在相同的用户上下文,但是CPU代表该任务运行内核代码。
较旧的Linux内核永远不会在任务忙于运行内核代码时抢占该任务。(请注意,I / O操作总是自愿重新安排。我说的是内核代码具有一些CPU密集型操作(例如对列表进行排序)的情况。)
如果系统允许该任务在 运行内核代码时 被抢占 , 则我们拥有所谓的“抢占式内核”。这样的系统不受系统调用期间可能遇到的不可预测的延迟的影响,因此它可能更适合嵌入式或实时任务。
例如,如果在一个特定的CPU上有两个任务可用,一个任务需要5毫秒才能完成一次系统调用,另一个任务是一个MP3播放器应用程序,需要每2毫秒传送一次音频管道,您可能会听到声音不连续。
反对抢占的论点是,可能在任务上下文中调用的所有内核代码都必须能够在抢占中幸存- 例如,存在许多不良的设备驱动程序代码,如果始终能够完成操作,那可能会更好。允许其他一些任务在该处理器上运行。(如今,使用多处理器系统作为规则而不是例外,所有内核代码都必须是可重入的,因此该参数在今天已经不那么重要了。)此外,如果可以通过改善syscall来改善不良情况来达到相同的目标。延迟,也许抢占是不必要的。
一个妥协方案是CONFIG_PREEMPT_VOLUNTARY,它允许在内核内部的某些点(但不是在所有地方)进行任务切换。如果只有少数地方可能陷入内核代码,这是一种减少延迟并保持复杂度可管理的廉价方法。