CHAPTER 4 THREADS,SMP,AND MICROKERNELS
4.1 进程和线程 进程的概念体现出两个特点: ①资源所有权:一个进程包括一个保存进程映像的虚地址空间,并且不时地被分配给对资源 的控制或所有权, . ②调度/执行:一个具有执行状态(运行、就绪等)和调度优先级的进程是一个被操作系统调度并分派的实体。 为区分这两个特点,调度并分派的部分通常称作线程或轻便进程(lightweight process),而资源所有权的部分通常仍称作进程或任务。
Multithreading (多线程) 多线程是指操作系统支持在一个进程中执行多个线程的能力。 传统的每个进程中只有一个线程在执行(没有考虑线程的概念),称作单线程方法。 例如图4.1 在多线程环境中,进程被定义成资源分配的实体(unit)和保护的实体(unit),即: ①保存进程映像的虚地址空间。 ②受保护地访问处理器、文件和I/O资源 等。
在进程中,每个线程有: ①线程执行状态(运行、就绪等)。 ②在未运行时保存的线程信息; ③一个执行栈。 ④每个线程静态存储局部变量。 ⑤对存储器和其进程资源的访问,并与该进程中的其他线程共享这些资源。 在单线程进程模型中 ,包括它的进程控制块和用户地址空间,以及用户栈和内核栈。
在多线程环境中,仍然有一个与进程相关联的进程控制块和用户地址空间,但是每个线程都有一个独立的栈和独立的控制块,包含寄存器值。优先级和其他与线程相关的状态信息。 进程中的所有线程共享该进程的状态和资源,它们驻留在同一块地址空间中,并且可以访问到相同的数据。 如图4.2所示
采用线程的优点: 1.在一个已有进程中创建一个新线程比创建一个全新进程所需的时间少。 2.终止一个线程比终止一个进程花费的时间少。 3.线程问切换比进程间切换花费的时间少。 4.线程提高了不同的执行程序间通信的效率。在大多数操作系统中,独立进程间的通信需要内核的干涉,以提供保护和通信所需要的机制。但是,由于在同一个进程中的线程共享存储空间和文件,它们无需调用内核就可以互相通信.。
调度和分派可以在线程基础上进行,因此大多数与执行相关的信息可以保存在线程级的数据结构中。 进程中的所有线程共享同一个地址空间,挂起涉及到把地址空间换出主存,因为进程中的所有线程共享同一个地址空间, 所有线程必须同时进入挂起状态。类似地,进程的终止会导致进程中所有线程的终止。
Thread Function( 线程功能) Thread State (线程状态):运行、就绪和阻塞。 与线程状态变化的4种基本操作: ①产生(Spawn):当产生一个新进程时,同时也为该进程产生了一个线程,随后,进程中的线程可以在同一个进程中产生另一个线程,新线程被放置在就绪队列中。 ②阻塞(B1ock):当线程需要等待一个事件时,它将阻塞,此时处理器转而执行另一个就绪线程。 ③解除阻塞(Unb1ock):当阻塞一个线程的事件发生时,该线程被转移到就绪队列中。 ④结束(Finish):当一个线程完成时,其寄存器的信息和栈都被释放。
在单线程程序中,结果是按顺序获得的,因此程序必须依次等待来自每个服务器的响应。 为每个RPC使用一个独立的线程,可以使速度有实质性的提高。如果这个程序在单处理器上运行,又有多个线程,那么必须顺序地产生请求并且顺序地处理结果,但是程序同时等待两个回答。 例如图4.3所示.
Thread Synchronization (线程同步) 一个线程对资源的任何修改都会影响同一个进程中其他线程的环境。 因此,需要各种线程的活动进行同步,以便它们互不干涉且不破坏数据结构。
图4.4单处理器上的多线程例子
User-Level and Kernel-Level Threads (用户级和内核级线程) 线程可以分为两类:用户级线程(ULT))和内核级线程(KLT),KLT又称作内核支持的线程或轻便进程。 用户级线程(User-Level Threads) 在一个纯粹的ULT软件中,有关线程管理的所有工作都由应用程序完成,内核没有意识到线程的存在。 描述此类线程的数据结构以及控制此类线程的原语在核外子系统中实现。
3.ULT可以在任何操作系统中运行,不需要对底层内核进行修改以支持ULT。线程库是一组供所有应用程序共享的应用级实用程序。 使用ULT代替KLT有很多优点: 1.由于所有线程管理数据结构都在一个进程的用户地址空间中,线程切换不需要内核模式特权,因此,进程不需要为了线程管理而切换到内核模式,这节省了在两种模式间进行切换从用户模式到内核模式;从内核模式返回到用户模式)的开销。 2.调用可以是应用程序专用的。一个应用程序可能倾向于简单的循环调度算法,而另一个应用程序可能倾向于基于优先级的调度算法。调度算法可以去适应应用程序,而不会扰乱底层的操作系统调度程序。 3.ULT可以在任何操作系统中运行,不需要对底层内核进行修改以支持ULT。线程库是一组供所有应用程序共享的应用级实用程序。
ULT相对于KLT有两个明显的缺点:1.在典型的操作系统中,许多系统调用都会引起阻塞,因此,当ULT执行一个系统调用时,不仅这个线程会被阻塞,进程中的所有线程都会被阻塞。
Kernel-Level Threads 描述此类线程的数据结构以及控制此类线程的原语在核心子系统中实现。 在一个纯粹的KLT软件中,有关线程管理的所有工作都是由内核完成的,应用程序部分没有进行线程管理的代码,只有一个到内核线程设施的应用程序编程接口(API)。 内核为该进程保存整个环境信息,并为进程中的各个线程保存它们的信息,调度是由内核基于线程的调度完成的。 描述此类线程的数据结构以及控制此类线程的原语在核心子系统中实现。
KLT方法的主要优点: 1.内核可以同时把同一个进程中的多个线程调度到多个处理器中;如果进程中的一个线程被阻塞,内核可以调度同一个进程中的另一个线程。 2.内核例程自身也是可以使用多线程的。 KLT方法的主要缺点是在同一个进程中把控制从一个线程传送到另一个线程, 需要内核的模式切换.
4.3 MICROKERNELS (微内核) 微内核是一个小型的操作系统核心。 提出的问题: 1.内核必须有多小才能称作微内核? 2.从硬件抽象出它们的功能时,怎样设计设备驱动程序才能获得最佳性能? 3.是在内核空间还是在用户空间运行一个非内核的操作? 4.是保留现有的子系统代码,还是从头开始?
在理论上,微内核的设计方法提供了高度的灵活性和模块性。 当今还有许多别的产品声称采用微内核实现,在不远的将来,这种通用的设计方法将用于大多数的个人计算机、工作站和服务器操作系统。
Microkernel Achitecture (微内核体系结构 ) 微内核的基本原理:只有最基本的操作系统功能才能放在内核中。不是最基本的服务和应用程序在微内核之上构造,并在用户模式下执行。 许多传统上属于操作系统一部分的功能现在都是外部子系统,包括设备驱动程序、文件系统、虚存管理程序、窗口系统和安全服务,它们可以与内核交互,也可以互相交互。
在微内核外部的操作系统部件被当作服务器进程实现; 借助于微内核传递消息来实现核外部件相互之间的交互。 微内核起着信息交换的作用:验证信息、在部件间传递信息并授权访问硬件。 微内核还执行保护功能,除非允许交换,否则它阻止信息传递。
图4.9 微内核体系结构
Benefits of a Microkernel organization (微内核组织结构的优点 ) 微内核结构为进程请求提供一致接口,进程不需要区分是内核级服务还是用户级服务,因为所有服务都是通过消息传递提供的。 微内核结构促进了可扩展性,允许增加新的服务以及在同一个功能区域中提供多个服务。 微内核结构具有灵活性。不仅可以在操作系统中增加新功能,还可以删除现有的功能,以产生一个更小、更有效的实现。
微内核结构具有可移植性。在微内核结构中,所有或者至少大部分处理器专用代码都在微内核中。因此,当把系统移植到一个处理器上时只需要很少的变化。 微内核结构的可靠性。小的微内核可以被严格地测试,它使用少量的应用程序编程接口(API),这就为核外部的服务产生高质量的代码。 微内核有助于分布式系统。在微内核级有一个系统映像,进程可以在不知道目标服务驻留在哪个机器上的情况下发送信息。
7. 许多微内核设计都朝着面向对象的方向发展。微内核结构是使用组件以搭积木的方式通过互连构造软件,组件中的所有交互都使用组件接口。 组件是具有明确定义的接口的对象。
Microkernel Performance (微内核性能) 微内核的一个潜在缺点是性能问题。即通过微内核构造和发送信息、接受应答并解码所花费的时间比进行一次系统调用的时间要多 。 解决这个问题的方法: 把一些关键的服务程序的驱动程序重新放回操作系统以增大微内核,它是以微内核的设计强度(最小的接口、灵活性等)为代价减少性能损失的。 使得微内核不会变大而会变小。通过正确的设计,一个非常小的微内核可以消除性能损失并提高灵活性和可靠性。
Microkernel Design (微内核设计 ) 由于不同的微内核具有不同的功能和大小,因而关于微内核应该提供什么功能以及实现什么结构并没有严格的规定。 微内核必须包括直接依赖于硬件的功能。这些功能通常可分为以下几类:低级存储器管理、进程间通信(IPC)以及I/O和中断管理。
Primitive Memory Management (低级存储器管理) 微内核必须控制物理地址空间,使得它可以在进程级实现保护。 以页式管理为例:提出了一组共三个微内核操作,用于支持内核外面的页面调度和虚拟存储管理: 1.Grant(授权):一个物理地址空间的所有者可以授权另一个进程使用它的某些页帧。内核把这些页帧从授予者的物理地址空间移出,并把它们分配给指定的进程。
2.Map(映射):一个进程可以把它的任何页帧映射到另一个进程的物理地址空间,使得两个进程都可以访问这些页帧。这就在两个进程间创建了共享存储区,内核把这些页帧分配给最初的所有者,但提供一个映射以允许其他进程的访问。 3. Flush(刷新):进程可以回收授权给进程的页帧,或映射到另外进程的任何页帧。 这种方案可以同时支持多个虚拟存储方案。
图4.10 缺页处理
Interprocess Communication (进程间的通信(IPC)) 微内核操作系统中进程之间或线程之间进行通信的基本形式是消息。 消息由头和体组成,头描述了发送消息和接收消息的进程,体中含有数据。 进程间通信基于与进程相关联的端口。 与端口相关联的是一组功能,用于表明哪些进程可以与这个进程进行通信。 端口的身份和功能由内核维护。
值得注意的是,物理地址空间不重叠的单独进程间的消息传递涉及到从存储器到存储器的复制,因而受存储器速度的限制。因此,当前对操作系统的研究热衷于基于线程的IPC和诸如页面重新映射(一个页面被多个进程共享)之类的共享存储器方案,以解决复制的系统开销。
I/O and Interrupt Management (I/O和中断管理 ) 微内核可以识别中断但不能处理中断,它仅产生一条消息给与该中断相关联的用户级进程。 微内核并不涉及设备专用的中断处理。 接收线程确定消息是否是来自一个中断,并确定具体是哪个中断。
用户级接收代码: driver thread: do waitFor(msg,sender); if ( sender==my_hardware_interrupt) { read/write I/O port; reset hardware interrupt; } else ……. while (true);