操作系统精髓与设计原理(原书第6版) 第四章 线程、对称多处理和微内核 学习笔记(2)

                          第四章  线程、对称多处理和微内核

 


4.3 微内核


1 微内核是一个小型的操作系统核心,他为模块化扩展提供基础。

2 分层的操作系统:所有功能按层次组织,旨在相邻层之间发生交互。在分层方法中,大多数层或所有层都在内核态下执行。

微内核的操作系统:将最基本的操作系统功能放在内核中,非基本的服务和应用程序在微内核之上构造,并在用户态下进行运行。

 

尽管什么应该在微内核中、什么应该在微内核外,不同的设计有不同的分界线,但是共同的特点是许多传统上属于操作系统一部分的功能现在都是外部子系统,包括设备驱动程序、文件系统、虚存管理程序、窗口系统和安全服务。它们可以与内核交互,也可以互相交互。

微内核结构用一个水平分层的结构代替了传统的纵向分层的结构。

微内核起着以下信息交换的作用:验证信息、在部件间传递信息并授权访问硬件。微内核还执行保护功能:除非允许交换,否则它阻止信息传递。

3 微内核组织的优点:

  1. 为进程发出的请求提供一致接口。不需要区分内核级还是用户级服务。
  2. 促进了可扩展性。允许增加新的服务以及在同一功能区域中提供多个服务。使用微内核结构,当增加一个新的功能时,只需要修改或添补选中的服务,而且修改不会导致需要构造一个新内核。
  3. 灵活性。该结构便于增加各种各样的功能。
  4. 可移植性。在微内核结构中,所以有或者大部分处理器的专用代码都在微内核中,当移植到其他系统上时只需要很小的变化,而且易于进行逻辑上的归类。
  5. 分布式系统支持。包括分布式操作系统控制的集群。
  6. 适用于面向对象操作系统环境。许多操作系统都朝着面向对象的方向发展。结合了微内核结构核OOOS原理的一种方法是使用构件。构件是具有明确定义接口的对象,可以以搭积木的方式通过互连构造软件,构造中的所有交互都是构件接口。

4 微内核的缺点:性能问题。解决放案有2种:(1)把一些关键的服务程序核驱动程序重新放回操作系统,浙江增大内核。这种方法以微内核的设计强度(最小的接口、灵活性)为代价。(2)通过正确的设计,一个非常小的微内核可以消除性能损失并提高灵活性和可靠性。

5 微内核必须包括直接依赖于硬件的功能,以及那些支持服务程序和应用程序在用户态下运行的功能。这些功能通常分为以下几类:低级存储管理,进程间通信,I/O和中断管理。

6 微内核必须控制硬件概念上的地址空间,使得操作系统可以在进程级实现保护。微内装只要负责把每个虚拟页映射到一个物理页框,而存储管理的大部分功能,包括保护一个进程的地址空间免于另一个进程的干涉,页面置换算法以及其他分页逻辑都可以在内核外实现。
7 可以在内核外面执行页面调度和虚存管理。当应用程序中的一个线程引用了不在内存中的一页时,会发生缺页中断并陷入到内核。内核给页面调度程序所在进程发送一条消息,表明引用哪一页。页面调度程序决定装载该页面并为此分配一个页框。页面调度程序和内核必须发生交互,以把页面调度程序的逻辑操作映射到物理内存。这个技术使得非内核进程可以把文件和数据库映射到用户地址空间而不需要调用内核。应用程序专用的存储共享策略可以在内核外实现。

8 用于支持内核外部的页面调度和虚存管理的三个微内核操作:

●授权,一个地址空间(进程)的所有者可以授权另一个进程使用它的某些页。内核把这些页从授予者的地址空间移出,并把它们分配给指定的进程。

●映射:一个进程可以把它的任何页映射到另-一个进程的地址空间,使得两个进程都可以访问这些页。这就在两个进程间创建了共享内存,内核把这些页分配给最初的所有者,但提供一个映射以允许其他进程的访问。

●刷新:进程可以回收授权给别的进程或映射到另外的进程的任何页。

9 微内核操作系统中进程之间或线程之间进行通信的基本形式是消息,消息由消息头和消息体组成,消息头描述了发送消息和接收消息的进程:消息体中含有数据,或者是指向一个数据块的指针,或者是关于进程的某些控制信息。
10 在典型情况下,我们认为进程间通信基于与进程相关联的端口。端口实际上是发往某个特定进程的消息队列。端口的标识和功能由内核维护。

11 地址空间不重叠的独立进程之间的消息传递涉及从内存到内存的复制。这样,由于受内存速度的限制,复制的速度就会远远低于处理器的速度。因此,当前对操作系统的研究热衷于基于线程的IPC和诸如页面重新映射(一个页面被多个进程共享)之类的共享内存方案。

12 在微内核结构中,可以做到以消息的方式处理硬件中断和把I/O端口包含到地址空间中。微内核可以识别中断但不处理中断,它产生一条消息给与该中断相关联的用户级进程。因此,当允许一个中断时,一个特定的用户级进程被指派给这个中断,并且由内核维护这个映射。把中断转换成消息的工作必须由微内核完成,但是微内核并不涉及设备专用的中断处理
13 硬件可看做一组具有唯一标识符的线程,并给用户空间中相关的软件线程发送消息(仅包含线程ID号)。接收线程确定消息是否来自一个中断,并确定具体是哪个中断。


4.4 Windows线程和SMP管理


1 Windows进程的重要特点:

    Windows进程作为对象实现。

    一个可执行的进程可能包含一个或多个线程。

    进程对象和线程对象都具有内置的同步能力。

2 下图展现了进程与他所控制或使用的资源关联的方式:每个进程都被指定一个安全访问令牌,称作进程的基本令牌。Windows使用这个令牌,使得用户可以访问受保护的对象,或者在系统上和受保护的对象上执行限定的功能。访问 令牌控制该进程是否可以改变自己的属性。进程不能直接修改这些结构,必须依赖于虚拟存储器管理,它为进程提供了内存分配服务。

3 Windows操作系统的进程对象于线程对象:

线程对象的一个属性是上下文环境,这个信息允许线程被挂起和恢复,此外,当线程被挂起时,可以通过修改该线程的上下文改变它的行为。

4 Windows支持进程间的并发行。同一个进程中的线程可以通过他们的公共地址空间交换信息,并访问进程中的共享资源,不同进程间的线程可以通过在两个进程之间建立的共享内存交换信息。

5一个面向对象的具有多线程的进程是实现服务器应用程序的一组有效的方法。

6 线程存在以下6种状态:

就绪态:可以被调度执行。内核分派器跟踪所有就绪线程,并按优先级顺序进行调度。

备用态:备用线程已经被选择下一次在一个特定的处理器上运行。该线程在这个状态等待,直到那个处理器可用。如果备用线程的优先级足够高,正在那个处理器上运行的线程可能被这个备用线程抢占。否则,该备用线程要等到正在运行的线程被阻塞或时间片结束。

运行态一旦内核分派器执行了线程切换,备用线程将进入运行状态并开始执行。执行过程一直持续到该线程被抢占、用完时间片、被阻塞或终止。在前两种情况下。它将回到就绪态。

等待态:当线程被一个事件(如I/O)阻塞、为了同步自愿等待或者一个环境子系统指引它把自身挂起时,该线程进入等待状态。当等待的条件满足时,如果它的所有资源都可用,线程转到就绪态。

过渡态:一个线程在等待后,如果准备好运行但资源不可用时,进入该状态。例如,一个线程的栈被换出内存。当该资源可用时,线程进入就绪状态。

终止态:一个线程可以被自己或者被另一个线程终止,或者当它的父进程终止时终止。一旦完成了清理工作,该线程从系统中移出,或者被执行体保留供以后重新初始化。

7 线程状态转换图如下:

8  创建进程的请求从一个应用程序发向相应的受保护的子系统,该子系统又给Windows执行程序发送一个进程请求,Windows创建一个进程对象并给子系统返问该对象的一个句柄。当Windows创建一个进程时,它不会自动创建线程。

9 在win32的情况下,一个新进程往往和一个线程一同创建。因此,对这类操作系统,子系统再次调用Windows进程管理器,为这个新进程创建一个线程,并从Windows接收该线程句柄,正确的线程和进程信息返回给应用程序。

10 16位Windows和POSIX不支持线程。

11 默认情况下,微内核在把线程指定到处理器时使用软亲和性的策略:分派器试图把一个就绪线程指定给上次运行它的同一个处理器。这有助于重新使用前一次执行该线程后仍处于处理器中的内存高速缓冲区中的数据。应用程序也可以限制它的线程在某些处理器上执行(硬亲和力)。

12 在没有亲和力限制的前提下,微内核把一个就绪线程制定给下一个可用的处理器,这就可以确保没有处理器时空闲的,或者确保当一个更高优先级的线程就绪时处理器不会去执行一个低优先级的线程。


4.5 Solaris的线程和SMP管理


1 Solaris使用了4个独立的与线程相关的概念:

进程:这是普通的Unix进程,包括用户的地址空间、栈和进程控制块。

用户级线程:通过线程库在进程地址空间中实现,他们对操作系统不可见的。用户级线程是进程内一个用户创建的执行单元。

轻量级进程: 轻量级进程可以看作是用户级线程和内核级线程间的映射,每个轻量级进程支持一个或多个用户级线程,并映射到一个内核级线程。轻量级进程由内核独立调度,可以在多处理器中并行执行。

内核线程:这是可以调度和分派到系统处理器上运行的基本实体。
2 下图展示了这4个实体之间的关系:

    每个轻量级进程严格对应于一个内核线程。

    轻量级进程对应用程序是可见的,所以轻量级进程的数据结构保存在他们各自的进程地址空间中。

    一些内核线程并没有于轻量级进程绑定。

3 Solaris系统使用了三层线程架构(用户级线程,轻量级进程,内核级线程)是为了辅助操作系统的线程管理,并向应用程序提供清晰的接口。

4 用户级线程接口可以是一个标准线程库。一个定义好的用户级线程映射到 一个轻量级进程上(由操作系统管理并定义执行状态),在执行状态中,一个轻量级进程以一对一的关系绑定到一个内核线程。所以并发和执行均是在内核线程的层面上来管理的。

5 Unix系统进程结构 Solaris系统的进程结构如下图所示:

由图4-16可知,Solaris系统基本保持了Unix系统的结构,但是用一组给每一个轻量级进程包含一个数据块的结构代替了处理器状态。

    轻量级进程数据结构包括以下元素:

●一个轻量级进程标识符。
●该轻量级进程和支持它的内核线程的优先级。

●一个信号掩码,告诉内核将接受哪个信号。
●当轻量级进程不在运行时保存的用户级寄存器的值。
●该轻量级进程的内核栈,栈中包含系统调用参数、结果和每个调用级别的错误代码

●资源的使用和统计数据。
●指向对应的内核级线程的指针。

●指向进程结构的指针。
6 简化了的线程执行状态图:

睡眠态:线程被阻塞。

僵死态:线程被终止。

自由态:线程资源已被释放,并等待从操作系统的线程数据结构中移出。

当一个线程被另-个更高优先级的线程抢占时,或者因为时间片用完 ,它会从执行态转入就绪态:当一个线程被阻塞时,它会从执行态变为睡眠态,且必须等待一个事件唤醒它,以便返回到就绪态。当一个线程调用了一个系统调用且必须等待系统服务完成时,就会发生阻塞。当一个线程的进程被停止时,该线程便进人停止态,这种情况可能是出于调试目的。

7 大多数操作系统包含两个基本形式的并发活动:进程和中断。Solaris系统把这两个概念统一到一个称作内核线程的模型和用于调度并执行内核线程的机制中,为实现这一点,中断被转换成内核线程。

8 把中断转换成线程的动机是减少开销。中断处理程序通常操作由内核其余部分共享的数据,因此,当访问这类数据的一个内核例程正在执行时,即使大多数中断不会影响到这些数据,中断也必须被阻塞。通常,实现这一点的方法是给这个例程设置中断优先级使它高于被阻塞的中断,并且当访问完成后,再降低优先级,这些操作都要花费时间。这些问题在多处理器系统中更为严重,内核必须保护更多的对象,并且可能需要在所有处理器上阻塞中断。

9 Solaris系统的解决方案总结如下:

1)Solaris使用了一组内核线程处理中断。和任何内核线程一样,中断线程有它自己的标识符、优先级、上下文和栈。
2)内核控制对数据结构的访问,并使用互斥原语在中断线程间进行同步。也就是说,通常用于线程的同步技术也可用于中断处理。

3)中断线程被赋予更高的优先级,高于所有其他类型的内核线程。


4.6 Linux的进程和线程管理


1 Linux的进程数据结构表示如下:

●进程间通信: Linux 支持UNIX SVR4中的IPC机制,

●链接:每个进程都有一个到它的父进程的链接以及到它的兄弟进程(与它有相同的父进程) 的链接和到所有子进程的链接。
●时间和计时器:包括进程创建的时刻和进程所消耗的处理器时间总量。一个进程可能还有一个或多个间隔计时器,它通过系统调用定义间隔计时器,其结果是当计时器期满时,给进程发送一个信号。计时器可以只用--次或周期使用。
●文件系统:包括指向被该进程打开的任何文件的指针和指向该进程当前和根目录的指针。

●地址空间:定义分配给该进程的虚拟地址空间。
●处理器专用上下文:构成该进程上下文的寄存器和栈信息。
●运行:这个状态值对应于两个状态。一个运行进程,或者正在执行,或者准备执行。

●可中断:这是一个阻塞状态,此时进程正在等待一个事件(如一个I/O 操作)的结束、一个可用的资源或另一个进程的信号。
●不可中断:这是另一种阻塞状态。它与可中断状态的区别是,在不可中断状态下,进程正在直接等待一个硬件条件,因此不会接受任何信号。
●停止:进程被终止,并且只能由来自另一个进程的主动动作恢复。例如,一个正在被调试的进程可以被置于停止状态。
●僵死:进程已经被终止,但是由于某些原因,在进程表中仍然有它的任务结构。

2 下图4.18给出了一个进程的执行状态,如下所示:

3 Linux提供一种不区分进程和线程的解决方案,通过使用一种类似于Solaris轻量级进程的方法,用户级线程被映射到内核级进程上。组成一个用户级进程的多个用户级线程被映射到共享同一组ID的多个Linux内核级进程上。这使得这些进程可以共享文件和内存等资源,使得同一组中的进程调度切换时不需要切换上下文。
4 在Linux中通过复制当前进程的属性可创建一个新进程。新进程被克隆出来以使它可以共享资源,如文件、信号处理程序和虚存。

5 当两个进程共享相同虚存时,它们可以被当做是一个进程中的线程。但是,没有为线程单独定义数据结构,因此,Linux中进程和线程没有区别。

6 Linux用clone()命令代替通常的fork()命令创建进程。这个命令包含了一组标识做为参数,正下表4.5中所定义的。传统的fork()系统调用在Linux上是用所有克隆标志清零的clone()系统调用实现的。
 

 7 当Linux内核执行从一个进程到另一个进程的切换时,它将检查当前进程的页目录地址是否和被调度的进程的相同,如果相同,那么它们共享同一个地址空间,所以此时上下文切换仅仅是从代码的一处跳转到代码的另一处。
8 虽然属于同一进程组的被克隆的进程共享同一内存空间,它们不能共享同一个用户栈。所以clone()调用为每个进程创建独立的栈空间。
 

 

 

 

 

 

 

 

 


 

     

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值