操作系统-进程与线程

  • 进程基本概念;
  • 进程状态及状态转换;
  • 进程控制块的作用和内容;
  • 进程控制操作;
  • 进程地址空间与进程映像;
  • 为什么引入线程?线程的应用场景;
  • Web服务器的实现;
  • 线程概念、线程与进程的区别;
  • 线程实现的三种方式;
  • Pthreads线程库及应用;
  • 几个重要的概念:原语、可再入程序。

进程的基本概念

1
2
3
4
5
多道程序设计 : 允许多个程序同时进入内存并运行, 提高系统效率

并发环境和并发程序 :
并发环境: 一段时间间隔内, 一个处理器上有 多个程序 处于开始允许但尚未结束的状态
并发程序: 在并发环境中的程序
  • 进程的定义
1
2
3
4
5
6
具有独立功能的程序 关于 某个数据集合上的一次运行活动, 系统资源分配和调度的独立单位  (又称 任务)
程序的一次支持过程
正在运行程序的抽象
并发,抽象为一个CPU变成多个CPU
系统资源分配单位,内存,文件。。。独立地址空间
操作系统将 CPU 调度给需要的 进程

进程控制块 PCB (又称 进程描述符,进程属性)

1
2
3
4
5
6
7
8
9
10
操作系统 控制和管理进程的数据结构 (保存了操作系统管理进程需要的信息)
记录进程的各种属性,描述进程的动态变化过程
是操作系统感知进程存在的唯一标志 (一个进程一个PCB)
进程表: 所有进程的PCB集合 (操作系统最多有多少个进程是固定的)

PCB包含信息
进程的描述信息
进程的控制信息
进程所拥有的资源和使用情况
CPU现场信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
进程描述信息: 
进程标识符(process ID), 唯一标识,整数
进程名, 通常是可执行文件名,不唯一
用户标识符 (创建进程的用户信息)
进程组关系 (父子进程等)

进程控制信息:
当前状态
优先级
代码执行入口地址
程序的磁盘地址
运行的统计信息(执行时间, 页面调度)
进程间同步和通信
进程的队列指针
进程的消息队列指针

所拥有的资源和使用情况:
虚拟地址空间的状况
打开文件的列表

CPU现场信息: (进程不运行时,操作系统保存的硬件执行状态)
寄存器值(通用寄存器,程序计数器PC,程序状态字PSW, 栈指针)
指向该进程页表的指针

进程状态及状态转换

三种基本状态

  • 运行态 : 占有CPU, 在CPU上执行
  • 就绪态 : 具备运行条件,但是没有空闲CPU,暂时不能执行
  • 等待态 : 因等待某个时间而暂时不能运行(如:等待读盘) - 又称为阻塞态,封锁态,睡眠态

三状态模型

进程三状态模型和状态转换

其他状态

1
2
3
4
5
6
7
8
9
10
创建态: 
已经完成进程创建的必要工作: 分配PID,填写PCB
但尚未同意执行该进程(如资源不足)

终止态:
终止执行后,完成一些数据统计工作,资源回收工作

挂起态:
用于调节负载 (CPU忙不过来)
进程不占用内存空间, 其进程映像交换到磁盘上

五状态模型

进程五状态模型和状态转换

七状态模型

进程七状态模型和状态转换

linux状态转换示意图

linux状态转换示意图

进程队列

按进程所处状态不同对进程进行管理

1
2
3
为每一类进程建立一个或多个队列  (如处于等待态, 按等待事件不同分多个队列)
队列元素为 PCB
伴随进程状态的改变,PCB从一个队列进入另一个队列

进程控制

完成进程各状态之间的转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
由特定功能的原语实现:  (原语: 原子操作,执行的程序不可分割,不可中断)
进程创建原语
进程撤销
进程阻塞,唤醒,挂起,激活
改变优先级
。。。

进程创建原语:
给新进程分配 唯一标识PID, 以及 进程控制块PCB
为进程分配 地址空间
初始化进程控制块 (设置默认值)
设置相应的队列指针 (插入进程队列,如就绪队列)

进程撤销原语: (结束进程)
收回进程所占有的资源 (关闭打开的文件,端口网络连接,回收分配的内存。。。)
撤销该进程的PCB
进程阻塞:
处于运行状态的进程,运行过程中期待某一事件发生而未发生时,进程自己执行阻塞原语,有运行态进入阻塞态

Unix常用进程控制操作 (都是系统调用)

1
2
3
4
fork():  通过 复制调用进程 来创建新的进程, 进程建立进程
exec(): 包括一系列系统调用,通过用新的程序代码覆盖原来的地址空间,实现进程执行代码的转换
wait(): 初级进程同步操作, 一个进程等待另一个进程结束
exit(): 终止一个进程的运行

一些进程的概念

1
2
3
4
5
6
7
8
进程不同角度的分类: 
系统进程 和 用户进程
前台进程 和 后台进程
CPU密集型进程 和 I/O密集型进程

进程的层次结构:
UNIX: init为根
Windows: 地位相等

进程地址空间

1
操作系统为 每个进程 分配 独立的相对进程地址空间

进程映像

对进程执行活动全过程的静态描述

1
2
3
4
5
6
7
8
9
10
由 进程地址空间内容,硬件寄存器内容, 该进程相关的内核数据结构,内核栈 组成

用户相关: 进程地址空间( 代码段,数据段,堆栈,共享库)

寄存器相关: 程序计数器,指令寄存器,程序状态寄存器,栈指针,通用寄存器 等的值

内核相关:
静态: PCB 及 各种资源数据结构
动态: 内核栈 (不同进程在进入内核后使用不同的内核栈)

上下文 (context)

1
2
3
4
5
6
将CPU硬件状态从一个进程换到另外一个进程的 过程称为 上下文切换

进程运行时: 硬件状态保存在CPU的寄存器中
进程不运行时: 这些寄存器的值保存在 进程控制块PCB中

操作系统运行新的进程时: 将PCB相关的值送到对应的寄存器中

线程

为什么在进程中引入线程

1
2
3
应用的需要  -  一个应用一个进程,但同时需要多个任务完成
开销的考虑 - 线程开销小,线程切换花费时间少, 线程之间共享内存和文件
性能的考虑

线程的基本概念

1
2
3
4
进程: 资源的拥有者

线程: CPU调度单位 (有了线程后继承了进程的基本属性)
在同一进程中增加了多个执行序列(线程)

线程的属性

1
2
3
4
5
6
7
8
标识符ID
状态及状态转换
不运行时需要保存的上下文(寄存器值)
有自己的栈和栈指针
共享进程的地址空间和相关资源
可以创建, 撤销 另外一个线程

程序开始以 一个单线程进程 运行

线程机制的实现

1
2
3
用户级线程
核心级线程
混合 - 以上两种方法结合

用户级线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
实现: 
在用户空间 建立 线程库 : 提供一组管理线程的过程
是运行时系统: 完成线程的管理工作(操作,线程表)
内核管理的还是进程,不知道线程的存在
线程切换不需要 内核态特权

UNIX - 一般就是用户级线程

例子:
POSIX线程库 -- PTHREAD
POSIX:多线程编程接口, 以线程库方式提供给用户

优点:
线程切换快
调度算法是应用程序特定的
用户级线程可运行在任何操作系统上 (只需要实现线程库)
缺点:
内核只将处理器分配给进程, 同一进程的两个线程不能同时运行在两个处理器上
大多数系统调用是阻塞的,因此,由于内核阻塞进程,进程中所有线程也被阻塞

核心级线程

彻底改造操作系统

1
2
3
4
5
6
内核进行所有线程的管理, 向应用程序提供API接口
内核维护进程和线程的上下文
线程的切换需要内核支持
以线程为基础进行调度

例子: Windows

混合模型

1
2
3
4
5
6
线程的创建在 用户空间  (用线程库完成)
线程调度等在 核心态完成

实现: 多个用户级线程 多路复用 多个内核级线程

例子: Solaris 操作系统

总结

进程

1
2
3
4
5
6
并发性: 任何进程可以与其他进程 一起向前推荐
动态性: 动态产生,动态消亡。 在生命周期内在三种基本状态之间转换
独立性: 资源分配 的独立单位
交互性: 进程在执行过程中 与 其他进程产生直接或间接的关系
异步性: 每个进程以其 相对独立,不可预知的速度 向前推进
进程映像: 程序 + 数据 + 栈(用户栈,内核栈)+ PCB

线程

1
2
3
多线程的应用场景
线程基本概念,属性
线程的实现机制

可再入程序 (可重入程序) 的概念

1
2
3
4
5
指的是可以被多个 进程同时调用的程序,因此对这个程序有限制。 
具有固定性质:
它是纯代码的, 在执行过程中这个代码不会改变。
那么如果有改变,就需要调用它的进程提供不同的数据区。改变的内容放在数据区,而代码部分是不再改变的。
那么可再入程序实际上是我们大部分 进程和线程都必须是可再入程序才能去运行