发布于 2013-05-27 05:01:08
Coroutines、光纤及其类似的类是由编程语言运行时或库管理的类似线程的执行上下文,而不是由操作系统管理的,操作系统认为它们是一成不变的。它们的用处有限;当真正的线程可用时,头脑清醒的人都不会使用这样的黑客。
简单地说,Linux使用先发制人的多任务处理。与早期Unix一样,早期Linux使用协作多任务处理来运行内核代码。这意味着进程可以在执行用户空间时被抢占,但不能在执行内核代码时被抢占。在运行内核代码时,进程只有在休眠时才会运行另一个进程,这是通过对一些休眠的阻塞函数进行一些自愿调用来实现的。这种方法极大地简化了操作系统内部,因为许多竞争条件都消失了。至少,如果只有一个处理器。运行内核代码的任务只需要担心中断,当中断不方便时,这些中断就可以被短暂地禁用。
随着20世纪90年代中期Linux1.3系列实验内核中引入了对多处理器的支持,这种情况开始发生变化。非抢占内核不支持SMP,因为为了维护协作多任务的保证,必须在内核周围放置一个大锁,这样每次只允许一个处理器进入。在Linux中,这被命名为BKL (大内核锁)。
渐渐地,BKL不再在所有进入内核的地方强制执行,而是被更细粒度的SMP锁所取代。一旦多个处理器同时在内核空间中运行,就会出现一种有趣的情况:真正的并发正在进行,受到锁定机制的保护,但是内核仍然是协作的,因为除非它休眠,否则任何任务都不会丢失它正在运行的处理器。
在这一点上,允许先发制人是合理的。因此,这被应用到内核中,以选项CONFIG_PREEMPT
的形式出现,它是经过多年试验的,并且倾向于在所有体系结构和与SMP的结合中不一致地工作。
内核之所以被抢占,只是因为它允许更好的实时处理:更短的事件响应时间。虽然抢占是有风险的,但大多数问题都是通过提高SMP的效率来解决的,这往往会降低采用优先购买权的门槛:也就是说,这不是“为什么,什么”的问题,而是“为什么不”的问题。
发布于 2013-05-27 04:13:28
线程和光纤都是抽象的,它们支持多个执行位置(代码路径)。
把它想象成一个特定的资源(CPU)是如何在这些位点之间共享的。给定CPU的执行轨迹是执行的位置。
对于线程,控制何时将CPU分配给线程,并删除(即当线程执行或不执行时)的控制是外部的。外部实体(内核调度程序)决定线程何时获得CPU以及多长时间。时间通常是一个因素。内核在多个线程之间共享CPU,如果某个线程在某一段时间后不自愿放弃CPU,内核将以公平的方式将其分配给另一个线程。内核可以使用各种调度算法来实现优先级、响应性和其他目标,但底线是CPU控制掌握在内核手中。
有了协同(或光纤),执行的地点就会让CPU保持它想要的时间,并且只自愿放弃它。这时,内核可以将CPU分配给另一个执行点。
请注意,“自愿”放弃CPU可以是显式的(通过使用某些系统调用),也可以是隐式的(当它内置到其他系统调用中时,比如信号量等待等等)。一般的经验法则是,如果系统调用中可能涉及等待,那么可能会在其中内置一个隐式调度点。
现在很明显,像Linux这样的通用内核并不是以一种大的方式使用协同机制。这是因为协同机制在放弃CPU时有太多的独立性。一个无赖的纤维或一个行为不端的人会占用CPU太长时间,并饥饿其他的执行位点。像Linux这样的执行环境,希望能够更好地控制CPU如何在所有执行位置之间进行调度。
发布于 2013-05-27 04:59:51
协作多任务者由于无法提供低延迟I/O性能而致命伤。
先发制人的多任务处理程序能够使I/O等待线程就绪/运行,在驱动程序从中断返回时抢占其他正在运行的线程,从而使GUI、浏览器等设备能够响应地运行,而视频/音乐播放器、BitTorrent、YouTube等则完全可以正常工作。
合作任务,如光纤和所谓的“绿色线程”,无疑在小众领域有其用途,但它们在通用操作系统中几乎毫无用处,这就是为什么Linux、Windows (反正是自W95 )等都使用先发制人的多线程(或者多进程,如果你愿意的话)调度器。
https://stackoverflow.com/questions/16765736
复制相似问题