一、介绍
进程中有两个重要概念:资源所有权、执行,因这一区别,许多操作系统中出现了称为 线程 的结构。
线程(Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
1. 进程与线程
进程 两个特点:
- 资源所有权:
进程包括存放进程映像的虚拟地址空间。进程总具有对资源(内存、I/O 通道设备、文件)的控制权 / 所有权。操作系统提供预防进程间发生不必要资源冲突的保护功能。 - 调度 / 执行:
进程执行时采用一个或多程序的执行路径 (轨迹),不同进程的执行过程会交替进行。因此,进程 具有多种状态、优先级,是可被调度的实体。
这两个特点相互独立,操作系统可分别进行处理。为区分它们,我们通常将分派的单位称为 线程 / 轻量级进程 (Light Weight Process, LWP),而将拥有 资源所有权的单位称为 进程 (Process) 或 任务 (Task)。
2. 多线程
多线程是指操作系统在单个进程内支持多个并发执行路径的能力。
在多线程环境中,进程定义为资源分配单元 和 一个保护单元:
进程相关的有:
- 容纳进程映像的虚拟地址空间。
- 对处理器、其他进程、文件、I/O 资源的受保护访问。
每个线程都有:
- 一个线程执行状态
- 未运行时保存的线程上下文
- 执行栈
- 存储局部变量的静态存储空间
- 线程间共享的内存、资源的访问
单线程、多线程进程模型:
比较性能,线程的优点如下:开销小!耗时短!效率高!
- 在已有的进程中创建一个新线程的时间,远少于创建一个全新进程的时间。
- 终止线程要比终止进程花费时间少。
- 统一进程内线程切换时间,少于进程间切换时间。
- 线程提高了不同执行程序的通信效率。
因此,一个应用程序实现,用一组线程比一组分离的进程更有效。
在单处理器上使用线程结构,可简化逻辑上从事几种不同的工作程序、结构。
线程的常见应用:
- 前台和后台工作
- 异步处理
- 执行速度(分治计算)
- 模块化应用设计
在支持线程的操作系统中,调度、分派是在线程基础上完成的,因此大多数执行相关的信息可以保存在线程级别的数据结构中。
3. 线程的功能
类似于进程,线程 也具有执行状态,且可彼此同步。
线程状态
线程的主要状态有 运行态、就绪态、阻塞态。因为线程依附于进程,挂起态对线程没有意义。
有 4 种与线程状态改变相关操作:
- 派生:
派生新进程时,同时也会为其派生一个线程,进程中的线程可以派生另一个线程,为其提供相关参数并放入就绪队列中。 - 阻塞:
等待事件时会被阻塞(保存线程的用户寄存器、程序计数器、栈指针),处理器执行另一个就绪线程。 - 解除阻塞:
发生阻塞事件时,线程会转入就绪队列。 - 结束:
一个线程 完成后,会释放其寄存器上下文、栈。
二、线程分类
线程 分为两大类,即用户级线程(User-Level Thread, ULT)和 内核级线程(Kernal-Level Thread, KTL),后者又称为内核支持的线程 / 轻量级进程。
1. 用户级线程
纯 ULT 软件中,管理线程的所有工作都由应用程序完成,内核意识不到线程的存在。
任何应用程序都可使用线程库设计成多线程程序,线程库是管理用户级线程的一个例程包,它含有创建 / 销毁线程的代码、在线程间传递消息和数据的代码、调度执行代码、保存 / 恢复线程上下文的代码。
用户级线程状态、进程状态间关系:
下面我们阐述线程调度、进程调度的关系:
我们以上图关系为例,分析线程、进程间状态关系:
- 线程阻塞进程:线程2 代码产生一个阻塞进程的系统调用,控制权交给内核,随后内核执行相应操作,把进程B置为阻塞态,并切换至另一个进程。在此期间,根据线程库维护的数据结构,此时 线程2 仍处于运行态。
- 时钟中断 :时钟中断将控制权交给内核,内核确定当前正在运行的 进程B 用完其时间片,内核将进程置于就绪态并切换至另一个进程。同时,线程库维护数据结构中,线程2 仍处于运行态。
- 进程内线程切换 :线程2 运行到需要 线程1 执行某个动作的时刻,此时 线程2 阻塞,线程1 从就绪态 转为运行态,进程自身仍在运行态。
纯 ULT 方案 优点:
- 所有线程数据结构都在一个进程地址空间内,切换避免两次模式 (用户、内核) 转换,节省开销。
- 调度可为应用程序定做调度算法(基于优先级 / 简单轮转)。
- 可在任何操作系统中运行,无需修改底层内核。
纯 ULT 方案 缺点:
- 部分操作系统中,系统调用会引起阻塞。
- 不能利用多处理技术,即同时执行部分代码,取代应用级线程多道程序设计。
2. 内核级线程
在纯 KLT 软件中,管理线程的所有工作均由内核完成。应用级没有线程管理代码,只有一个到内核线程设施的应用编程接口(API)。
这种方案内核为进程、内部线程维护上下文。
首先,内核可以同时把同一个进程中的多个线程调度到多个处理器中。
其次,进程中的一个线程被阻塞时,内核可以调度同一个进程中的另一个线程。
且内核例程自身也可以是多线程的。
KLT 主要缺点:控制权在线程间转移时,需切换到内核模式。
操作 | 用户级线程 | 内核级线程 | 进程 |
---|---|---|---|
Null Fork (派生开销) | 34 | 948 | 11300 |
Signal Wait (同步时间) | 37 | 441 | 1840 |
混合方法:
3. 其他方案
线程 : 进程 | 描述 | 实例系统 |
---|---|---|
1 : 1 | 执行的每个线程是唯一的进程,他有自己的地址空间和资源。 | 传统UNIX |
M : 1 | 一个进程顶定义了一个地址空间、动态资源所有权。 可在该进程中创建、执行多个进程。 | Windows NT、Solaris、Linux, OS/2、OS/390、MACH |
1 : M | 一个线程可以在进程环境间迁移,允许线程在不同系统中移动。 | Ra(Clouds)、Emerald |
M : N | 结合了1 : M和M : 1的属性 | TRIX |
多对多关系:
TRIX操作系统有两个重要概念:域、线程:
- 域: 静态实体,包括一个地址空间、发送 / 接收消息的端口
- 线程: 执行路径,含有执行栈、处理状态、调度信息
多个线程可在一个域中执行,多个域也可使用一个线程,线程可在域之间移动。
一对多关系:
在分布式操作系统中,线程可在地址空间中作为实体移动。在以 Ra 为内核的 Clouds 操作系统,从用户角度来看,线程是一个活动单元,进程是一个带有相关进程控制块的虚拟地址空间。线程创建后,会通过调用该进程中一个程序的入口点,开始在进程中执行。线程可在地址空间之间转移,甚至跨越机器边界。
另一个著名的例子是Emerald操作系统。
三、多核 & 多线程
多核系统上的软件性能
多核组织结构带来的性能提升,取决于应用程序有效利用并行资源的能力。
Amdahl定律:
加
速
比
=
单
个
处
理
器
执
行
时
间
在
N
个
并
行
处
理
器
上
执
行
时
间
=
1
(
1
−
f
)
+
f
/
N
加速比 = \frac{单个处理器执行时间}{在N个并行处理器上执行时间}=\frac{1}{(1 - f) + f / N}
加速比=在N个并行处理器上执行时间单个处理器执行时间=(1−f)+f/N1
该定律假设程序执行时间的 (1 - f) 分之一所涉及的代码本质上是串行的,其余 f 分之一所设计的代码时无限并行的,并且没有调度开销。