操作系统 为什么用户线程必须映射到内核线程
内核线程是可以被处理器调度和执行的实际线程。用户程序也可以制定自己的调度计划,但这些并不是内核线程。每个用户线程不能单独执行,因此需要一个内核级线程。
因此,为了使用户级线程取得进展,用户程序必须通过其调度程序将用户级线程运行在内核级线程上,而为此我们需要不同的映射方法。在继续之前,您需要简要了解用户线程、内核线程及其映射。
什么是线程
线程是计算机系统中CPU利用率的基本原子单位。我们通常认为进程是CPU利用率的基本单位,但一个进程可以进一步分成多个线程来执行。进程可以划分为不同的任务或单位,这些单位可以独立执行,这些单位就被称为线程。
线程是一个轻量级进程,可以由调度程序独立管理。它通过并行执行提高应用程序的性能。线程与其对等线程共享诸如数据段、代码段文件等信息,同时它包含自己的寄存器、堆栈、计数器等。计算机系统中创建的两种主要类型的线程是:
- 用户线程
- 内核线程
线程可以在进程的地址空间内创建,即在进程内核参与或不参与的情况下创建。
什么是用户线程
用户线程是由用户使用用户库创建的线程,只对创建进程及其运行时环境可见,而内核对于这些线程的创建并不知情。用户线程仅停留在创建进程的内存空间中,并由创建进程运行和管理,无需内核的参与。
用户级线程较小且比内核级线程运行速度更快。它们由程序计数器(PC)、堆栈、寄存器和一个小型的进程控制块表示。
优势
用户级线程的一些优势如下:
- 用户级线程的创建比内核级线程更容易快捷,也更易于管理。
- 用户级线程可以在任何操作系统上运行。
- 在用户级线程中,线程切换不需要内核模式特权。
劣势
用户级线程有以下劣势:
- 用户级线程的多线程应用无法利用多处理器的优势。
- 如果一个用户级线程执行阻塞操作,整个进程都会被阻塞。
什么是内核线程
另一方面,内核级线程是由操作系统直接处理的,内核负责线程管理。内核管理进程及其线程的上下文信息。因此,与用户级线程相比,内核级线程较慢。
优势
内核级线程的一些优势如下:
- 相同进程的多个线程可以在内核级线程中被安排在不同的处理器上。
- 内核例程也可以是多线程的。
- 如果一个内核级线程被阻塞,内核可以调度同一进程的另一个线程。
劣势
内核级线程也有以下劣势:
- 在进程中从一个线程转移到另一个线程时,需要进行一次模式切换到内核模式的操作。
- 与用户级线程相比,内核级线程的创建和管理速度较慢。
用户线程如何映射到内核线程
用户线程通过线程库映射到内核线程。这种映射的方式被称为 线程模型 。
将用户线程映射到内核线程是通过 虚拟处理器 来实现的。虚拟处理器(VP)通常是一个隐式库实体,它是一个内核线程或绑定到内核线程的结构。对于用户线程而言,虚拟处理器的行为类似于一个CPU。
存在以下可能的线程模型,所有模型都用于将用户级线程映射到内核级线程。
- M:1 模型: 在M:1模型中,所有用户线程都映射到一个内核线程。这个进程一次只能运行一个用户级线程,因为与该进程关联的只有一个内核级线程。一个库调度程序处理映射,并且库完全处理所有用户线程编程设施。这个模型可以在任何系统上使用,特别适用于传统的单线程系统。
- 1:1 模型: 在1:1模型中,每个用户线程映射到一个内核线程。每个用户级线程在一个单独的内核级线程上执行,或者每个用户线程在一个VP上运行。大多数用户线程编程设施由内核线程直接处理。这个模型是默认模型。
- M: N 模型: 在M: N模型中,所有用户线程都映射到一个内核线程池;所有用户线程在一个虚拟处理器池上运行。该进程被分配m个内核级线程来执行n个用户级线程。一个用户线程可以被绑定到一个特定的VP,如1:1模型中。所有未绑定的用户线程共享剩下的VP。
- 两级模型: 两级模型与M: N模型类似,但还允许将某些用户级线程绑定到单个内核级线程。
在M: N模型和两级模型中,内核必须有某种方法与用户级线程管理器进行通信,以维护分配给进程的适当数量的内核线程。这个机制被称为 调度程序激活 。
内核向应用程序提供一组内核线程(虚拟处理器),然后应用程序完全控制哪个线程在每个内核线程上运行。内核根据系统中不同进程之间的竞争需求来控制设置中的内核线程数量。
内核通过从内核到用户级线程管理器的 上调 来通知用户级线程管理器重要的内核事件。
例如 ,让我们研究一个如何使用调度程序激活的例子。
- 内核为一个拥有三个用户级线程的进程分配了 一个内核线程 。
- 这三个用户级线程轮流在单个内核级线程上执行。
- 正在执行的线程进行 阻塞系统调用 。
- 内核阻塞调用的用户级线程和用于执行该用户级线程的内核级线程。
- 调度器激活: 内核决定为该进程分配一个 新的内核级线程 。
- 上调: 内核 通知 用户级 线程管理器 哪个用户级线程现在被阻塞,并提供一个新的内核级线程。
- 用户级线程管理器将其他线程移动到新的内核线程上,并恢复一个准备好的线程。
- 当一个用户级线程被阻塞时。
- 其他线程可以轮流在新的内核线程上执行。
为什么用户线程必须映射到内核线程
用户线程需要映射到内核线程,因为是内核将线程调度到CPU上执行,为此,内核必须了解它要调度的线程。
一个进程创建的所有用户线程都在被指派给整个进程的内核级线程上执行。每当轮到指定进程在CPU上执行时,它的内核线程就会被调度到CPU上。进程中的所有其他用户线程必须逐一映射到创建进程时指定的内核线程上才能执行。
由于它们都由创建进程本身控制,因此用户线程必须逐一映射到指定的内核线程上,并因此执行。