Version: Next

进程定义

程序:就是一个指令序列

  • 早期计算机只支持 单道程序
  • 引入 多道程序 后:内存中出现 多个程序段多个数据段
    • 需要在他们之间找到正确的地址进行切换
    • IO 系统也要响应进行切换以实现被多个程序共用
  • 为了操作系统管理,完成各程序并发执行,引入了 进程进程实体 的概念

进程控制块

  • 系统为每个运行的程序配置一个数据结构,称为 进程控制块 PCB (Process Control Block),用来描述进程的各种信息

进程实体

  • PCB、程序段、数据段 三部分构成了 进程实体 也称 进程映像,简称 进程
  • 所谓创建进程:实质上是创建进程实体中的 PCB
  • 所谓撤销进程:实质上是撤销进程实体中的 PCB
  • PCB 是进程存在的唯一标志

等价定义

从不同的角度,进程可以有不同的定义,他们都强调 动态性,比较传统典型的定义有:

  1. 进程是程序的一次执行过程
  2. 进程是一个程序及其数据在处理机上顺序执行时所发生的活动
  3. 进程是具有独立功能的程序在数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位

引入进程实体的概念后,可把进程定义为:

  • 进程进程实体运行过程,是系统进行 资源分配调度 的一个独立单位
注意

严格来说,进程实体和进程并不一样

  • 进程实体是静态的,进程则是动态的
  • 不过除非明确区分,一般情况下认为进程实体就是进程
    • 因此一般可以说,"进程由程序段、数据段、PCB 三部分组成"

进程控制块 —— PCB

操作系统通过 PCB 来管理进程,因此 PCB 中应该包含操作系统对其进行管理所需的各种信息

  • PCB
    • 进程描述信息
      • 进程标识符 PID
      • 用户标识符 UID
    • 进程控制和管理信息
      • 进城当前状态
      • 进程优先级
    • 资源分配清单
      • 程序段指针
      • 数据段指针
      • 键盘
      • 鼠标
      • ..
    • 处理机相关信息
      • 各种寄存器

进程的组织

随着系统中 PCB 数目的激增,应当用适当的方式把这些 PCB 组织起来

  • 进程的组成:讨论一个银城内部由哪些部分构成
  • 进程的组织:讨论多个进程之间的组织问题
  • 链接方式
    • 按照进程状态将 PCB 分为多个 队列
    • 操作系统持有指向各个队列的指针
  • 索引方式
    • 根据进程状态的不同,建立几张索引表
    • 操作系统持有指向各个索引表的指针

链接方式

  • 执行指针:指向当前处于运行状态的进程
  • 就绪表指针:指向当前处于就绪状态的进程,各个 PCB 通过链表形成一个队列,通常会把优先级高的进程放在队头
  • 阻塞表指针:指向当前处于阻塞态的进程,很多操作系统还会根据阻塞原因不同,再分为多个阻塞队列

索引方式

  • 执行指针:指向当前处于运行状态的进程
  • 就绪表指针:指向当前处于就绪状态的进程,各个 PCB 的地址存储在就绪索引表中
  • 阻塞表指针:指向当前处于阻塞态的进程,各个 PCB 的地址存储在阻塞索引表中

进程的特征

进程和程序是两个截然不同的概念

相比于程序,进城拥有以下特征:

  • 动态性:进程是程序的一次执行过程,是 动态 的产生、变化和消亡的
  • 并发性:内存中有多个进程实体、各进程可并发执行
  • 独立性:进程是能独立运行、独立获得资源、独立接收调度的基本单位。进程是资源分配、接收调度的基本单位
  • 异步性:各进程按各自独立的、不可预知 的速度向前推进,操作系统要提供 ”进程同步机制“ 来解决异步问题
  • 结构性:每个进程都会配置一个 PCB ,结构上看,进程由 程序段、数据段、PCB 组成

进程的状态与转换

进程状态

状态

  • 运行状态
  • 就绪状态
  • 阻塞状态
  • 创建状态
  • 终止状态

其中:运行状态就绪状态、阻塞状态 称为三种 基本状态

  • 运行态(Running):占有 CPU,并在 CPU 上运行
  • 就绪态 (Ready):已经具备运行条件,但由于没有空闲的 CPU,而暂时不能运行
  • 阻塞态 / 等待态(Blocking / Waiting):因等待某一事件而暂时不能运行

创建、终止状态,主要处理 PCB、程序段、数据段 的开辟与销毁

进程状态转换

进程状态间的转换:

  • 就绪态 → 运行态
  • 运行态 → 就绪态
  • 运行态 → 阻塞态
  • 阻塞态 → 就绪态

image-20210426135400898


进程控制

原语 实现进程控制

进程控制概念

进程控制:对系统中的所有进程实施有效的管理,具有 创建新进程撤销已有进程实现进程状态转换 等功能

  • 就是实现进程的状态转换

  • 原语 实现进程控制:

    • 原语:特点是执行期间 不允许中断,只能一气呵成,即 原子操作
    • 原语采用 关中断指令开中断指令 实现
    • 原语是一种特殊的程序
    • 原语处于操作系统最底层,是最接近硬件的部分
    • 原语程序运行时间短、调用频繁

进程控制相关原语

进程控制导致进程状态转换,无论哪个原语,要做的无非三类事情:

  1. 更新 PCB 中的信息:如 修改进程状态标志、将运行状态保存到 PCB、从 PCB 恢复运行环境
    1. 所有的进程控制原语一定都会修改进程状态标志
    2. 剥夺当前运行进程的 CPU 使用权必然需要保存其运行环境
    3. 某进程开始运行前必然要恢复其运行环境
  2. 将 PCB 插入合适的队列
  3. 分配、回收资源

创建原语——进程的创建

无 → 创建态 → 就绪态

  • 申请空白 PCB
  • 为新进程分配所需资源
  • 初始化 PCB
  • 将 PCB 插入就绪队列

撤销原语——进程的终止

就绪态 / 阻塞态 / 运行态 → 终止态 → 无

  • 从 PCB 集合中找到终止进程的 PCB
  • 若进程正在运行,立刻剥夺 CPU,将 CPU 分配给其他进程
  • 终止其所有子进程
  • 将该进程拥有的所有资源归还刚给父进程或操作系统
  • 删除 PCB

阻塞原语——进程的阻塞

运行态 → 阻塞态

  • 找到要阻塞的进程对应的 PCB
  • 保护进程的运行现场,将 PCB 状态信息设置为 阻塞态,暂时停止进程运行
  • 将 PCB 插入相应事件的等待队列

唤醒原语——进程的唤醒

阻塞态 → 就绪态

  • 在时间等待队列中找到 PCB
  • 将 PCB 从等待队列移除,设置进程为就绪态
  • 将 PCB 插入就绪队列,等待调度

切换原语——进程的切换

运行态 → 阻塞态 / 就绪态 → 就绪态 → 运行态

  • 将运行环境信息存入 PCB
  • PCB 移到相应队列
  • 选择另一个进程执行,并更新其 PCB
  • 根据 PCB 恢复新进程所需的环境

进程通信

  • 共享存储:
    • 基于数据结构的共享
    • 基于存储区的共享
  • 消息传递:
    • 直接通信方式
    • 间接通信方式
  • 管道通信

进程通信——各进程之间的信息交换

  • 进程是分配操作系统资源的单位(包括内存地址空间),因此 各进程拥有独立的内存地址空间
  • 为了保证系统安全性,一个进程不能直接访问另一个进程的地址空间,但有时进程之间的信息交换是必须的,因此操作系统必须提供一些进程间安全通信的办法

共享存储

在内存中设立一块两个进程共享的空间

  • 两个进程对共享空间的 访问 必须是 互斥
  • 互斥访问可以通过操作系统提供的工具实现
  • 操作系统只负责提供共享空和同步互斥工具(如 P、V 操作)

基于数据结构的共享

  • 基于固定的数据结构,比如共享空间里只能存放一个长度为 10 的数组
  • 这种共享方式速度慢,限制多,是一种 低级通信 方式

基于存储区的共享

  • 在内存中画出一块共享存储区,数据的形式、存放位置都由进程控制,而不是操作系统
  • 这种共享方式速度快,是一种 高级通信 方式

管道通信

管道是指用于连接读写进程的一个共享文件,有名 PIPE 文件

  • 其实就是在内存中开辟一个大小固定的缓冲区
  • 管道只能采用 半双工通信,某一时间段内只能实现单向的传输;如果要实现双向同时通信,则需要设置两个管道
  • 各进程必须 互斥 的访问管道
  • 数据以 字符流 的方式写入管道,当 管道写满 时,写进程write() 系统调用被 阻塞,等待读进程将数据取走;当读进程将数据全部取走后,管道变空,此时 读进程read() 系统调用将被 阻塞
  • 如果没写满,就不允许读;如果没读空,就不允许写
  • 数据一旦被读出,就从管道中被抛弃,这意味着 读进程最多只能有一个,否侧可能会有读错数据的情况

消息传递

进程间的数据交换以 格式化的消息 Message 为单位

  • 进程通过操作系统提供的 发送消息接收消息 两个 原语 进行数据交换
  • 消息包含 消息头消息体
    • 消息头:发送进程ID、接收进程ID、消息类型、消息长度等格式化的信息

直接通信方式

  • 消息直接挂到接收进程的消息缓冲队列上

间接通信方式

  • 消息要先发送到中间实体(邮箱)中,因此也称 信箱通信方式

线程

有的进程可能需要 ”同时“ 做很多事,而传统的进程只能串行地执行一系列程序,为此引入了 线程,以增加并发度

  • 传统的进程是程序执行流的最小单位
  • 引入线程后,线程成为了程序执行流的最小单位
  • 可将线程理解为轻量级进程
  • 线程是一个基本的 CPU 执行单元,也是程序执行流的最小单位
  • 引入线程后,不仅是 进程之间可以并发进程内的各线程之间也可以 并发,从而进一步提升了系统的并发度,使得一个进程内可以并发处理多个任务(如 QQ 内视频、文字聊天、传输文件)
  • 引入县城后,进程 只作为 除 CPU 之外的系统资源的分配单元(如打印机、内存地址空间等都是分配给进程的)

引入线程带来的变化

  • 资源分配、调度
    • 传统进程机制中,进程是资源分配、调度的基本单位
    • 引入线程后,进程是资源分配的基本单位,线程是调度的基本单位
  • 并发性
    • 传统进程机制中,只能进程间并发
    • 引入线程后,各线程间也能并发,提升了系统并发度
  • 系统开销
    • 传统的进程间并发,需要切换进程的运行环境,系统开销很大
    • 线程间并发,如果是同一进程内的线程切换,则不需要切换进程环境,系统开销小
    • 引入线程后,并发带来的系统开销减小

线程的属性

  • 线程是处理机调度的单位
  • 多 CPU 计算机中,各线程可占用不同的 CPU
  • 每个线程都有一个线程ID、线程控制块 TCB
  • 线程也有就绪、阻塞、运行三种基本状态
  • 线程几乎不拥有系统资源
  • 同一进程的不同线程间共享进程的资源
  • 由于共享内存地址空间,同一进程中的线程间通信甚至无需系统干预
  • 同一进程中的线程切换,不会引起进程切换
  • 不同进程中的线程切换,会引起进程切换
  • 切换同进程中的线程,系统开销很小
  • 切换进程,系统开销较大

线程的实现方式

用户级线程

User-Level Thread,ULT

image-20210426152217152

  • 用户级线程由应用程序通过线程库实现
  • 所有的 线程管理工作 都由 应用程序负责 (包括线程切换)
  • 用户级线程中,线程切换 可以在 用户态 下完成,无需操作系统干预
  • 在用户看来,是有多个线程;但在操作系统内核看来,并意识不到线程的存在(用户级线程对用户不透明,对操作系统透明)
  • 用户级线程,就是从用户视角出发,能看到的线程

内核级线程

Kernel-Level Thread,KLT;又称 内和支持的线程

image-20210426152357383

  • 内核级线程的管理工作由 操作系统内核 完成
  • 线程调度、切换等工作都由内核负责,因此内核级线程的切换,必然需要在 核心态 下才能完成
  • 内核级线程,就是从操作系统内核视角看,才能看到的线程
重点

操作系统只 ”看得见“ 内核级线程,因此只有内核级线程才是处理机分配的单位


多线程模型

在同时支持用户级线程和内核级线程的系统中,由几个用户级线程映射到几个内核级线程的问题,引入了 多线程模型 问题

  • 多对一模型:多个用户级线程映射到一个内核级线程,每个用户进程只能对应一个内核级线程
    • 优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高
    • 缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行
  • 一对一模型:图如 "内核级线程" 的图。一个用户级线程映射一个内核级线程。每个用户进程有与用户级线程相同数目的内核级线程
    • 优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行
    • 缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大
  • 多对多模型:n 个用户级线程映射到 m 个内核级线程上,n ≥ m。
    • 集先前二种模型之所长