为什么 Linux 不使用纤程而不是抢占式多任务?

0x9*_*x90 4 linux multithreading kernel multiprocessing

  1. 有人可以解释一下协程和纤维是什么吗?与常规例程和多任务机制相比,它们解决了什么问题。
  2. 为什么 Linux 使用抢占式多任务而不是协作式多任务?

Kaz*_*Kaz 6

协程、纤程和它们的同类是类似线程的执行上下文,由编程语言运行时或库管理,而不是由操作系统管理,操作系统将它们视为一个步骤。它们的用途有限;当真正的线程可用时,头脑正常的人不会使用这样的技巧。

简单地说,Linux 使用抢占式多任务处理。与早期的 Unix 一样,早期的 Linux 使用协作多任务来运行内核代码。这意味着进程可以在执行用户空间时被抢占,但不能在执行内核代码时被抢占。在运行内核代码时,一个进程只有在它休眠时才被调度为运行另一个进程,这是通过主动调用某个休眠的阻塞函数来实现的。这种方法极大地简化了操作系统的内部结构,因为很多竞争条件都消失了。至少,如果只有一个处理器。运行内核代码的任务只需要担心中断,当它们不方便时可以暂时禁用它们。

随着 1990 年代中期在实验性 Linux 1.3 内核系列中引入对多处理器的支持,这种情况开始发生变化。非抢占式内核不能很好地支持 SMP,因为为了保证协作多任务处理,必须在内核周围放置一个大锁,一次只允许一个处理器进入。在 Linux 中,这被命名为 BKL(大内核锁)。

渐渐地,BKL 不再在所有进入内核的入口处强制执行,而是被更细粒度的 SMP 锁取代。一旦你有多个处理器同时在内核空间内运行,就会出现一个有趣的情况:真正的并发正在发生,受到锁定机制的保护,但内核仍然是合作的,因为任何任务都不会失去它正在运行的处理器除非它睡觉。

在这一点上,只允许抢占是有意义的。因此,CONFIG_PREEMPT它以选项的形式进入内核,该选项经过多年的实验,往往无法在所有架构中始终如一地工作,并与 SMP 结合使用。

内核可抢占的原因很简单,因为它允许更好的实时处理:对事件的响应时间更短。虽然抢占是有风险的,但大多数问题都是通过提高 SMP 的效率来解决的,这往往会降低采用抢占的门槛:也就是说,这不是“为什么,为什么”的问题,而是“为什么不”的问题。

  • 实际上,*用户级*光纤非常有用。它们的一个巨大优势是可以更好地控制某些东西运行的“时间”。如果您正确使用光纤,那么当您设置光纤时,您可以放心,从流程的 POV 来看,(1) 它将在您准备切换到它时准确启动,并且 (2) 它不会“不要放弃CPU,直到它准备好(阅读:直到东西回到一致的状态)。这正是您在线程中放弃的控制类型。您可以尝试重新获得一些控制权,但如果您只想在任务之间切换,为什么要放弃它呢? (2认同)