进程调度

进程的资源分配与调度

线程调度

一对一模型

一对一模型中,每个用户线程都对应各自的内核调度实体。内核会对每个线程进行调度,可以调度到其他处理器上面。当然由内核来调度的结果就是:线程的每次操作会在用户态和内核态切换。另外,内核为每个线程都映射调度实体,如果系统出现大量线程,会对系统性能有影响。但该模型的实用性还是高于多对一的线程模型。Linux Thread 与 NPTL 都是采用这种模型。

在 Linux 中通过 LWP(lightweight process)作为线程概念的支持,轻量级线程(LWP)是一种由内核支持的用户线程。它是基于内核线程的高级抽象,因此只有先支持内核线程,才能有 LWP。每一个进程有一个或多个 LWPs,每个 LWP 由一个内核线程支持。这种模型实际上就是恐龙书上所提到的一对一线程模型。在这种实现的操作系统中,LWP 就是用户线程。

由于每个 LWP 都与一个特定的内核线程关联,因此每个 LWP 都是一个独立的线程调度单元。即使有一个 LWP 在系统调用中阻塞,也不会影响整个进程的执行。轻量级进程具有局限性。首先,大多数 LWP 的操作,如建立、析构以及同步,都需要进行系统调用。系统调用的代价相对较高:需要在 user mode 和 kernel mode 中切换。其次,每个 LWP 都需要有一个内核线程支持,因此 LWP 要消耗内核资源(内核线程的栈空间)。因此一个系统不能支持大量的 LWP。

多对一模型

多对一线程模型中,线程的创建、调度、同步的所有细节全部由进程的用户空间线程库来处理。用户态线程的很多操作对内核来说都是透明的,因为不需要内核来接管,这意味不需要内核态和用户态频繁切换。线程的创建、调度、同步处理速度非常快。当然线程的一些其他操作还是要经过内核,如 IO 读写。这样导致了一个问题:当多线程并发执行时,如果其中一个线程执行 IO 操作时,内核接管这个操作,如果 IO 阻塞,用户态的其他线程都会被阻塞,因为这些线程都对应同一个内核调度实体。在多处理器机器上,内核不知道用户态有这些线程,无法把它们调度到其他处理器,也无法通过优先级来调度。

多对多模型

用户线程库还是完全建立在用户空间中,因此用户线程的操作还是很廉价,因此可以建立任意多需要的用户线程。操作系统提供了 LWP 作为用户线程和内核线程之间的桥梁。 LWP 还是和前面提到的一样,具有内核线程支持,是内核的调度单元,并且用户线程的系统调用要通过 LWP ,因此进程中某个用户线程的阻塞不会影响整个进程的执行。用户线程库将建立的用户线程关联到 LWP 上, LWP 与用户线程的数量不一定一致。当内核调度到某个 LWP 上时,此时与该 LWP 关联的用户线程就被执行。