答案 0 :(得分:4)
简化说Linux使用抢先式多任务处理。与早期的Unix一样,早期的Linux使用协作式多任务来运行内核代码。这意味着可以在执行用户空间时抢占进程,但不能在执行内核代码时抢占进程。在运行内核代码时,一个进程被取消调度,只有在它休眠时才运行另一个进程,这通过对一些休眠的阻塞函数进行一些自愿调用来实现。这种方法极大地简化了操作系统内部,因为许多竞争条件都消失了。至少,如果只有一个处理器。运行内核代码的任务只需要担心中断,并且只要它们不方便就可以暂时禁用。
随着1990年代中期实验性Linux 1.3内核系列中多处理器的支持,这种情况开始发生变化。非抢占式内核不能很好地支持SMP,因为为了保持协作式多任务的保证,必须在内核周围放置一个大锁,一次只允许一个处理器进入。在Linux中,这被命名为BKL(大内核锁)。
渐渐地,BKL并没有在所有进入内核的过程中被强制执行,而是被更细粒度的SMP锁取代。一旦你有多个处理器同时在内核空间内运行,就会出现一个有趣的情况:真正的并发正在进行,受到锁定机制的保护,但内核仍然是合作的,因为没有任务可以丢失它运行的处理器除非它睡着了。
此时允许抢占是有道理的。因此,它以选项CONFIG_PREEMPT
的形式进入内核,该选项多年来一直在试验,并且在所有体系结构中以及与SMP结合使用时都不能始终如一地工作。
为什么内核可以被抢占只是因为它允许更好的实时处理:更短的事件响应时间。虽然先发制人是有风险的,但大多数问题都是通过提高SMP效率来解决的,这往往会降低采用先发制人的标准:即不是“为什么,为什么”,而是“为什么不”。< / p>
答案 1 :(得分:2)
线程和光纤都是抽象,可以实现多个执行位点(代码路径)。
将其视为在这些基因座之间共享某种资源(CPU)的方式。给予CPU的执行轨迹是执行的。
对于线程,控制CPU何时被给予线程并被带走(即当它执行时没有)是外部的。外部实体(内核调度程序)决定线程何时获取CPU以及多长时间。时间通常是一个因素。内核在多个线程之间共享CPU,如果一个线程在一定时间后没有自愿放弃CPU,内核将把它拿走并以合理的方式将其交给另一个线程。内核可以使用各种调度算法,实现优先级,响应性和其他目标,但最重要的是CPU控制权掌握在内核手中。
使用协同程序(或光纤),执行的位置可以根据需要保留CPU,并且只能自动放弃。此时,内核可以将CPU分配给另一个执行位置。
请注意,“自愿”放弃CPU可以是显式的(通过使用某些系统调用),也可以是隐式的(当它内置到其他系统调用中时,如信号量等待等)。一般的经验法则是,如果系统调用中可能涉及等待,则可能会在其中内置隐式调度点。
现在可能很明显,像Linux这样的通用内核不会大量使用协同程序。这是因为协同程序在放弃CPU时具有太多的独立性。流氓光纤或行为不端的人可能会长时间占用CPU,并使其他执行地点挨饿。像Linux这样的执行环境,可以更好地控制CPU在所有执行位置中的调度方式。
答案 2 :(得分:1)
合作多任务处理器由于无法提供低延迟I / O性能而致命地致残。
抢占式多任务程序使I / O等待线程准备好/运行,抢占其他正在运行的线程,驱动程序从中断返回的能力允许GUI,浏览器等响应式运行和视频/音乐播放器,BitTorrent,YouTube等实际上都可以工作。
合作任务,如纤维和所谓的绿线&#39;毫无疑问它们在利基领域有用,但它们在通用操作系统中是无用的,这就是为什么Linux,Windows,(因为W95,无论如何)等等都使用先发制人的原因。多线程,(或多处理,如果你愿意),调度程序。