操作系统精髓:线程、对称多处理SMP和微内核

1.进程和线程

进程的概念包含两个特点:
# 资源所有权
    回顾:一个进程包括一个存放进程映像的虚拟地址空间,进程映像中包括程序、数据、栈和进程控制块中定义的属性
    一个程序总是拥有对资源的控制或所有权,这些资源包括内存、I/O通道、I/O设备和文件,操作系统提供保护,以防止进程之间发生不必要的与资源相关的冲突
# 调度/执行
    一个进程沿着通过一个或多个程序的一条执行路径执行,执行过程可能与其他进程的执行过程交替进行
    一个进程具有一个执行状态(执行、就绪等)和一个分配的优先级,并且是一个可被操作系统调度和分派的单元

为了区分这两个特点,分派的单元称作线程或轻量级进程Light Weight Process LWP,而拥有资源所有权的单位称作进程或任务

1.1 多线程

多线程:操作系统在单个进程内支持多个并发执行路径的能力
单线程:传统的一个进程中只有一个线程在执行

在多线程环境下,进程被定义为资源分配的单元和一个被保护的单位,与进程相关联的有:
# 存放进程映像的虚拟地址空间
# 受保护地对处理器、其他进程(用于进程间通信)、文件和I/O资源(设备和通道)的访问

线程相关联的有:
# 线程执行状态(运行、就绪态)
# 在未运行时保存的线程上下文
# 一个执行栈
# 用于每个线程局部变量的静态存储空间
# 与进程内的其他线程共享的堆进程的内存和资源的访问

单线程进程模型:
包括进程控制块、用户地址空间、在进程执行过程中管理调用/返回行为的用户栈和内核栈
多线程进程模型:
进程仍旧只有一个与之关联的程序控制块和用户地址空间,但其中的每一个线程都有自己独立的线程控制块和栈
其中,线程控制块包含寄存器值、优先级和其他与线程相关的状态信息
进程的所有线程共享该进程的状态和资源,它们驻留在同一块地址空间中,并且可以访问相同的数据

线程性能优点:
创建时间更短,终止花费较少,切换时间快,提高了不同执行程序间通信的效率
大多数进程间通信需要内核的介入,以提供保护和通信所需要的机制;
由于同一个进程中的线程共享内存和文件,它们无需调用内核就可以通信。

在支持多线程的操作系统中,调度和分派是在线程基础上完成的,因此大多数与执行相关的信息可以保存在线程级的数据结构中。

1.2 线程功能特性

线程状态:与进程一样,线程的关键状态有运行态、就绪态和阻塞态,一般来说,挂起态对线程没有什么意义,挂起态是一个进程级概念
如果一个进程被换出,由于它所有的线程共享该进程的地址空间,因此它们也必须被换出

4种与线程状态改变相关的基本操作:
# 派生
    典型情况下,派生出一个新进程时,同时也为该进程派生一个线程
    随后,进程中的线程可以在同一个进程中派生出另一个线程,并为新线程提供指令指针和参数,新线程拥有自己的寄存器上下文和栈空间,且被放置在就绪队列中
# 阻塞
    当线程等待一个事件时,它被阻塞(保留用户寄存器、程序计数器、栈指针),处理转而执行同一进程中的其它就绪线程
# 解除阻塞
    等待事件发生,线程解除阻塞,加入就绪队列
# 结束
    线程完成,其寄存器上下文和栈被释放

线程同步:
进程所有线程共享同一地址空间和进程资源,线程同步带来的问题和使用的技术通常与进程同步相同

1.3 用户级和内核级线程

线程的实现可以分为两大类:用户级线程(User-Level Thread ULT)和内核级线程(Kernel-Level Thread KLT)(又称内核支持的线程或轻量级进程)

# 用户级线程

在一个纯用户级线程软件中,有关线程管理的所有工作都有应用程序完成,内核意识不到线程的存在。
任何应用程序都可以通过使用线程库被设计成多线程程序。
线程库是用于用户级线程管理的一个例程包,包含创建和销毁代码、在线程间传递消息和数据、调度线程和保存和回复线程上下文

默认情况下,应用程序从单线程开始,并在该线程中开始运行,该应用程序和它的线程被分配给一个由内核管理的进程。
在应用程序运行的任何时刻,应用程序都可以派生一个相同进程中运行的新线程。

派生线程是通过调用线程库中的派生例程完成的。通过过程调用,控制权被传递给派生例程。此时要保存当前线程的上下文。
线程库为新线程创建了一个数据结构,然后使用某种调度算法,包控制权传递给该进程中处于就绪态的一个线程,此时需要恢复线程的上下文。
这里的上下文包括用户寄存器内容、程序计数器和栈指针。

优点:
# 所有的线程管理数据结构都在一个进程的用户地址空间中,线程切换不需要内核态特权,进程切换就不需要为了线程管理而切换到内核态
# 调度可以是应用程序相关的,而不是使用功能操作系统调度
# 用户级线程可以在任何操作系统中运行,不需要对底层内核进行修改以支持用户级线程
缺点:
# 很多系统调用都会引起阻塞,不光该线程被阻塞,进程中所有线程都会被阻塞
# 纯粹的用户级线程策略中,一个多线程程序不能利用多处理技术。
    内核一次只能将一个进程分配给一个处理器,因此一个进程中只有一个线程可以执行。

#   内核级线程

在纯的内核级线程软件中,有关线程管理的所有工作都是由内核完成的,应用程序没有管理线程的代码。
内核为进程及其内部的每个线程维护上下文信息,调度是由内核基于线程完成的。

这样克服了用户级线程的两个缺陷:
# 内核可以同时将一个进程的多个线程调度到多个处理器
# 进程中一个线程被阻塞,内核可以调度同一进程的其它线程
同时,内核例程自身也可以使用多线程。

主要缺点:
在把控制从一个线程转入同一个进程的另一个线程时,需要内核的状态切换。

2 对称多处理SMP Symmetric Multi-Processing

传统上,计算机被看做事顺序机器,大多数计算机编程语言要求程序员把算法定义成指定序列。处理器通过顺序逐条地执行机器指令来执行程序。
试图实现并行处理的两个流行的通过复制处理器提供并行性:对称多处理SMP和集群。

2.1 SMP体系结构

并行处理器系统分类:
1)单指令单数据SISD流:
    单处理器处理单指令流,对保存在单个内存中的数据进行操作
2)单指令多数据SIMD流:
    一个机器指令控制多个处理部件步伐一致地同时执行
3)多指令单数据MISD流:
    一系列数据被传送到一组处理器上,每个处理器执行不同的指令序列
4)多指令多数据MIMD流:
    一组处理器同时在不同的数据集上执行不同的指令序列

在MIMD结构中,处理器是通用的,因为它们能够处理执行相应的数据转换所需的所有指令。
每一个处理器都有一个专用内存,那么每一个处理部件都可以被看做是一个独立的计算机。
计算机间的通信或者借助于固定的路径,或者借助于某些网络设施,这类系统称作集群(cluster),或多计算机系统。
如果处理器共享一个公用内存,每一个处理器都访问保存在共享内存中的程序和数据,处理器之间通过共享内存相互通信,这类系统成为共享内存多处理器系统。

    
共享内存多处理器系统,将进程分配给处理器基本方法:
# 主/从
    操作系统内核总是在特定的处理器上运行,其他处理器只用于执行用户程序或部分操作系统实用程序。
    主处理器负责调度进程或线程
# 对称
    在对称多处理系统中,内核可以在任何处理器上执行,并且通常是每一个处理器从可用的进程或线程池中进行自己的调度工作
    内核可以由多进程或多线程组成,允许部分内核并行执行

2.2 SMP系统的组织结构

SMP中有多个处理器,每个都含有自己的控制单元、算术逻辑单元和寄存器,每个处理器都可以通过某种形式的互连机制访问一个共享内存和I/O设备,共享总线是一种通用办法。处理器可以通过内存相互通信,也可以直接交换信号。

3.微内核

3.1 微内核体系机构

微内核是一个小型的操作系统核心,它为模块化扩展提供基础。
微内核的基本原理,只有最基本的操作系统功能才能放在内核中。
许多传统上属于操作系统一部分的功能现在都是外部子系统,包括设备驱动程序、文件系统、虚拟内存管理程序、窗口系统和安全服务。

微内核结构用一个水平分层的结构代替了传统的纵向分层的结构。
在微内核外部的操作系统部件被当做服务器进程实现,它们可以借助于通过微内核传递消息来实现相互间的交互。
因此,微内核起着消息交换和保护功能。

3.2 微内核组织结构的优点:
1)一致性接口
    进程不需要区分内核级服务还是用户级服务,因为所有服务都是通过消息传递提供的。
2)可扩展性
    允许增加新的服务以及在同一个功能区域中提供多个服务
3)灵活性:服务可增可删
4)可移植性:
    在微内核结构中,所有或至少大部分处理器专用代码都在微内核中,系统移植只需做很少的改变
5)可靠性
6)分布式系统的支持
7)对面向对象操作系统的支持

3.3 微内核性能
通过微内核构造和发送消息、接受应答并解码所花费的时间比进行一次系统调用的时间要多。

3.4 微内核设计

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

1)低级内存管理

微内核必须控制硬件概念上的地址空间,使得操作系统可以在进程级实现保护,微内核只要负责把每个虚拟页映射到一个物理页框,
而存储管理的大部分功能,包括保护一个进程的地址空间免于另一个进程的干涉,页面置换算法以及其他分页逻辑都可以在内核外实现

2)进程间通信

微内核操作系统中进程之间或线程之间进行通信的基本形式是消息。
消息由消息头和消息体组成,消息头描述发送消息和接收消息的进程,消息体中含有数据,或者指向一个数据库的指针,或者关于进程的某些控制信息。

典型情况下,认为进程间通信是基于进程间相关联的端口,端口实际上是发往某个特定进程的消息队列。
端口实际上是发往某个特定进程的消息队列。端口的标识和功能由内核维护,通过给内核发送一条指明新端口功能的消息,进程就允许对自身授权新的访问。

3)I/O和中断管理

微内核识别中断但是不处理中断,它产生一条消息给与该中断相关联的用户级进程。
当允许一个中断时,一个特定的用户级进程被指派给这个中断,并且由内核维护这个映射,把中断转换为映射的工作由微内核完成,但微内核不涉及设备专用的中断处理。

4.Windows线程与SMP管理

Windows内核所提供的进程结构和服务是相当简单和通用的,允许每个OS子系统模拟某种特定的进程结构和功能:
1)Windows进程作为对象实现
2)一个可执行的进程可能有一个或多个线程
3)进程对象和线程对象都具有内置的同步能力

每个进程都被指定一个安全访问令牌,称作进程的基本令牌。
当用户初次登录时,Windows创建一个包括用户安全ID的访问令牌。Windows使用这个令牌,使得用户可以访问受保护的对象。
与进程相关的还有定义当前分派给该进程的虚拟地址空间的一系列块。进程不能直接修改这些结构,必须依赖于虚拟存储管理器,它为进程提供了内存分配服务。
进程还包含一个对象表,表中有该进程知道的其它对象的句柄。对象中包含的每个线程都有一个句柄。
此外,进程可以访问一个文件对象和一个定义一段共享内存的段对象。

4.1 进程对象和线程对象

Windows使用两种与进程相关的对象:进程对象和线程对象
进程是对应一个拥有内存、打开的文件等资源的用户作业或应用程序的实体
线程是顺序执行的一个可分派的工作单元,并且它是可中断的。

每个进程由许多属性定义,并且封装了它可执行的许多行为和服务。
一个进程在收到相应的消息后将执行一个服务,调用这类服务的唯一方法是给提供该服务的进程对象发送消息。

一个Windows进程至少包含一个执行线程,该线程可能会创建别的线程。
在多处理器系统中,同一个进程的多个线程可以并行地执行。
线程对象的一个属性是上下文环境,这个信息允许线程被挂起和恢复。

4.2 多线程

Windows支持进程间的并发性,此外同一个进程的多个线程可以分配给不同的处理器并且同时执行。
同一进程的线程可以通过它们的公共地址空间交换信息,并访问进程中的共享资源,不同进程中的线程可以通过在两个进程间建立的共享内存交换信息。

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

4.3 线程状态

六种状态:
1)就绪态:内核分派器跟踪所有就绪线程,并按优先级顺序进行调度
2)备用态:已经被选择下一次在一个特定的处理器上运行
3)运行态:执行一直持续直到被抢占、用完时间片、被阻塞或终止
4)等待态:
5)过渡态
6)终止态

5.Linux的进程和线程管理

5.1 Linux任务
Linux中的进程或任务由一个task_struct数据结构表示,包含如下信息:
1)进程状态:进程的执行状态,包括执行态、就绪态、挂起态、停止态、僵死态
2)调度信息:调度进程所需信息
3)标识符:每个进程唯一的进程标识符,还有用户标识符和组标识符,组标识符用来为一组进程指定资源访问特权
4)进程间通信:Linux支持UNIX SVR4的IPC机制
5)链接:每一个进程都有到它父进程和所有子进程的连接以及它兄弟进程的连接
6)时间和计时器:进程创建时间和进程所消耗的处理器时间总量
7)文件系统:包括被该进程打开的文件指针和指向该进程当前和根目录的指针
8)地址空间:分配给该进程的地址空间
9)处理器专用上下文:构成上下文的寄存器和栈信息
10)运行:
11)可中断
12)停止
13)僵死

5.2 Linux线程

多线程应用程序需要用一组用户级程序库来编写,以便将所有的线程映射到一个单独的内核级进程中,最著名的是pthread库。

Linux不区分进程和线程,也没有单独为线程定义数据结构,用户级线程被映射到内核级进程上。
组成一个用户级进程的多个用户级线程被映射到共享同一组ID的多个Linux内核级进程上,这使得这些进程可以共享文件和内存等资源,也使得同一组的进程调度切换时不需要切换上下文。
在Linux中通过复制当前进程的属性可创建一个新进程,新进程被克隆出来,以使它可以共享资源,当两个进程共享相同虚存时,它们可以被当做是一个进程中的线程,但是不同的进程依旧要创建属于自己的栈空间。

Linux使用clone命令代替通常的fork命令创建进程,传统的fork系统调用在Linux上是用所有克隆标志清零的clone系统调用实现的。
当Linux内核执行从一个进程到另一个进程的切换时,它将检查当前进程的页目录地址是否和将被调度的进程的相同。如果相同,则是共享同一地址空间的进程,此时上下文的切换只是从代码的一处跳转到代码的另一处。

你可能感兴趣的:(操作系统,操作系统,并行处理,内核,进程与线程)