操作系统 | 学习笔记 | 王道 | 2.1 进程与线程
2.1 进程与线程
文章目录
- 2.1 进程与线程
- 2.1.1 进程的概念和特征
- 2.1.2 进程的状态与转换
- 2.1.3 进程的组织方式
- 2.1.4 进程控制
- 2.1.5 进程的通信
- 2.1.6 线程和多线程模型
- 错题总结:
2.1.1 进程的概念和特征
-
进程的概念
进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
进程实现操作系统的并发性和共享性。
程序:是静态的,就是个存放在磁盘里的可执行文件,如:QQ.exe。
进程:是动态的,是程序的一次执行过程,或者是一个正在运行的程序,如:可同时启动多次QQ程序。
进程实体:即进程映像,是静态的,可理解为进程的一次时刻的状态。
作业:用户向计算机提交的一项任务,是静态的,它通常是一个批处理程序或一个后台程序。
-
进程实体的组成
-
程序控制块PCB
PCB是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收其PCB。
- 进程描述信息
- 进程标识符PID:当进程被创建时,操作系统会为该进程分配一个唯一的、不重复的“身份证号”–PID(Process ID,进程ID)
- 用户标识符UID
- 进程控制和管理信息
- CPU、磁盘、网络流量使用情况统计…
- 进程当前状态:就绪态/阻塞态/运行态.…
- 资源分配清单
- 正在使用哪些文件
- 正在使用哪些内存区域
- 正在使用哪些I/O设备
- 处理机相关信息(CPU现场信息):如PSW、PC等等各种寄存器的值(用于实现进程切换)
- 进程描述信息
① PCB,即进程控制块,操作系统需要对各个并发运行的进程进行管理, 但凡管理时所需要的信息,都会被放在 PCB 中。
② PCB 是进程存在的唯一标志。
③ PCB 存于内存的内核区,注意内存的内核区和 OS 的内核态的区别,内核程序运行在内核态。- 程序段:程序的代码(指令序列)
- 数据段:运行过程中产生的各种数据(如:程序中定义的变量)
①PCB 是给操作系统用的,程序段和数据段是给进程自己用的。
②引入进程实体的概念后,可把进程定义为是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
-
-
进程的特征
- 动态性:进程是程序的一次执行过程,是动态地产生、变化和消亡的;动态性是进程最基本的特征。
- 并发性:内存中有多个进程实体,各进程可并发执行
- 独立性:进程是能独立运行、独立获得资源、独立接受调度的基本单位
- 异步性:各进程按各自独立的、不可预知的速度向前推进,异步性会导致并发程序执行结果的不确定性。
- 结构性:每个进程都会配置一个PCB。结构上看,进程由程序段、数据段、PCB组成
2.1.2 进程的状态与转换
-
基本状态
-
运行态。占有CPU,并在CPU上运行;√CPU√其他所需资源
-
就绪态。已具有运行条件,但无空闲CPU,暂时不能运行;×CPU√其他所需资源
系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。
-
阻塞态,又称等待态。因等待某一事件暂时不能运行;×CPU×其他所需资源
系统通常将处于阻塞态的进程也排成一个队列,甚至根据阻塞原因的不同,设置多个阻塞队列。
-
创建态。进程正在被创建,尚未转到就绪态。OS为进程分配系统资源、初始化PCB
- 首先申请一个空白PCB,并向PCB中填写用于控制和管理进程的信息
- 然后为该进程分配运行时所必须的资源
- 最后把该进程转入就绪态并插入就绪队列
但是,如果进程所需的资源尚不能得到满足,如内存不足,则创建工作尚未完成,进程此时所处的状态称为创建态。
-
终止态。进程正从系统中消失,进程正常结束或其他原因退出运行。OS回收进程拥有的资源,撤销PCB
-
-
进程状态的转换
- 就绪态一>运行态:进程被调度
- 运行态一>就绪态:时间片到 or CPU被其他进程抢占
- 运行态一>阻塞态:等待系统资源分配or等待某事件发生(主动行为)
- 阻塞态一>就绪态:资源分配到位,等待的事件发生(被动行为)
- 创建态一>就绪态:系统完成创建进程相关的工作
- 运行态一>终止态:进程运行结束 or 运行过程中遇到不可修复的错误
2.1.3 进程的组织方式
-
链接方式
链接方式是将同一状态的进程的PCB组成一个双向链表,称为进程队列。
- 结构:每个队列的队首和队尾都有一个指针,指向第一个和最后一个PCB。每个PCB中也有两个指针,分别指向前一个和后一个PCB。这样,就可以方便地在队列中插入或删除PCB。
- 优点:简单、灵活
- 缺点:查找效率低,需要遍历链表
-
索引方式
索引方式是将所有的PCB存放在一张索引表中,每个表项包含一个PCB的地址和状态信息。
- 结构:索引表可以是顺序表或散列表,可以按照进程号或其他关键字进行排序或散列。
- 优点:查找效率高,可以快速定位到某个PCB
- 缺点:需要额外的空间存储索引表,且索引表的大小受限于内存容量
2.1.4 进程控制
进程控制就是要实现进程状态的转换,通过原语实现。
-
进程的创建
-
创建原语:操作系统创建一个进程时使用的原语,其操作如下;创建态→就绪态
- 申请空白PCB
- 为新进程分配所需资源
- 初始化PCB
- 将PCB插入就绪队列
-
引起进程创建的事件
- 用户登录:分时系统中,用户登录成功,系统会建立为其建立一个新的进程
- 作业调度:多道批处理系统中,有新的作业放入内存时,会为其建立一个新的进程
- 提供服务:用户向操作系统提出某些请求时,会新建一个进程处理该请求
- 应用请求:由用户进程主动请求创建一个子进程
-
父子进程
允许一个进程创建另一个进程,此时创建者称为父进程,被创建的进程称为子进程。
- 进程可以继承父进程所拥有的资源。
- 当子进程被撤销时,应将其从父进程那里获得的资源归还给父进程。
- 在撤销父进程时,通常也会同时撤销其所有的子进程。
-
-
进程的终止
-
撤销原语:其操作如下;
就绪态/阻塞态/运行态→终止态→无
- 从PCB集合中找到终止进程的PCB
- 若进程正在运行,立即剥夺CPU,将CPU分配给其他进程
- 终止其所有子进程
- 将该进程拥有的所有资源归还给父进程或操作系统
- 删除PCB
-
引起进程终止的事件
- 正常结束:进程自已请求终止(exit系统调用)
- 异常结束:整数除以0、非法使用特权指令,然后被操作系统强行杀掉
- 外界干预:Ctrl+Alt+delete,用户选择杀掉进程
-
-
进程的阻塞
-
阻塞原语:其操作如下;
运行态→阻塞态
- 找到要阻塞的进程对应的PCB
- 保护进程运行现场,将PCB状态信息设置为“阻塞态,暂时停止进程运行
- 将PCB插入相应事件的等待队列
-
引起进程阻塞的事件
- 需要等待系统分配某种资源
- 需要等待相互合作的其他进程完成工作
-
-
进程的唤醒
-
唤醒原语:其操作如下;
阻塞态→就绪态
- 在事件等待队列中找到PCB
- 将PCB从等待队列移除,设置进程为就绪态
- 将PCB插入就绪队列,等待被调度
-
引起进程唤醒的事件
- 等待的事件发生:因何事阻塞,就应由何事唤醒
阻塞原语唤醒原语必须成对使用
-
-
进程的切换
-
切换原语:其操作如下;
运行态→就绪态,就绪态→运行态
- 将运行环境信息存入PCB
- PCB移入相应队列选择
- 另一个进程执行,并更新其PCB
- 根据PCB恢复新进程所需的运行环境
-
引起进程切换的事件
- 当前进程时间片到
- 有更高优先级的进程到达
- 当前进程主动阻塞
- 当前进程终止
-
2.1.5 进程的通信
低级通信方式:PV操作。高级通信方式:共享存储、消息传递、管道通信。
-
共享存储
设置一个共享空间,通过对其进行读/写操作实现信息交换
在对共享空间进行写/读操作时,需要使用同步互斥工具(如PV操作)。
共享存储分为两种:
-
低级方式:基于数据结构的共享
比如共享空间里只能放一个长度为10的数组。这种共享方式速度慢、限制多,是一种低级通信方式
-
高级方式:基于存储区的共享
操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式。
进程之间共享空间需要通过特殊的系统调用实现;进程内线程共享进程空间。
-
-
消息传递
在消息传递系统中,进程间的数据交换以格式化的消息(Message)为单位。
进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。
在微内核操作系统中,微内核与服务器之间的通信就采用了消息传递机制。
消息格式:
- 消息头:发送进程ID、接受进程ID、消息长度等格式化的信息
- 消息体
通信方式:
-
直接通信方式:发送进程直接把消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上,接收进程从消息缓冲队列中取得消息。
-
间接通信方式:送进程通过信箱间接地通信,将消息发送到某个中间实体,接收进程从中间实体取得消息。该通信方式广泛应用于计算机网络中。
-
注:可以多个进程往同一个信箱 send 消息,也可以多个进程从同一个信箱中 receive 消息。
用发送原语和接收原语实现基于信箱的进程间通信
-
管道通信
管道是一个特殊的共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的内存缓冲区。
管道通信允许两个进程按生产者-消费者方式进行通信。各进程要互斥访问管道。
- 写满时,不能再写,读空时,不能再读
- 没写满时,不能读,没读空时,不能写
一个管道只能实现半双工通信;实现双向同时通信要建立两个管道
- 管道本质上是一种特殊的文件。相比于普通的文件通信,其区别如下:
- 限制管道的大小。管道文件是一个固定大小的缓冲区,使得它的大小不像普通文件那样不加检验地增长。
- 读进程也可能工作得比写进程快。读空时再读管道会被阻塞,而不是调用返回文件结束。
- 管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:
- ①一个管道允许多个写进程,一个读进程(2014年408真题高教社官方答案);
- ②允许有多个写进程,多个读进程,但系统会让各个读进程轮流从管道中读数据(Liux的方案)。
管道只能由创建进程所访问,当父进程创建一个管道后,由于管道是一种特殊文件,子进程会继承父进程的打开文件,因此子进程也继承父进程的管道,并使用它来与父进程进进行通信。
2.1.6 线程和多线程模型
-
线程的基本概念
线程可理解为轻量级进程,它是一个基本的CPU执行单元,也是程序执行流的最小单位。
线程由线程ID、程序计数器、寄存器集合和堆栈组成。
引入进程的目的是更好地使多道程序并发执行,提高资源利用率和系统吞吐量;
而引入线程的目的则是减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。
引入线程后,进程只作为除CPU外的系统资源的分配单位,线程则作为处理机的分配单元
-
线程与进程的比较
传统进程机制 引入线程后 资源分配、调度 进程是资源分配、调度基本单位 进程是资源分配基本单位 线程是资源调度基本单位 并发性 进程间并发 线程间也能并发 拥有资源 拥有资源的基本单位 不拥有系统资源 独立性 进程间独立地址空间和资源 同进程下的线程共享地址空间和资源 系统开销 需要切换进程运行环境,开销大 同一进程内线程,不需切换进程环境,开销小 支持多处理机系统 进程只能运行在一个处理机上 进程中多个线程可以分配到多个处理机执行 -
线程的属性
多线程操作系统中的进程已不再是一个基本的执行实体,但它仍具有与执行相关的状态。所谓进程处于“执行”状态,实际上是指该进程中的某线程正在执行。
- 线程是处理机调度的单位
- 多CPU计算机中,各个线程可占用不同的CPU
- 每个线程都有一个线程ID、线程控制块(TCB)
- 线程也有就绪、阻塞、运行三种基本状态
- 线程几乎不拥有系统资源
- 同一进程的不同线程间共享进程的资源
- 由于共享内存地址空间,同一进程中的线程间通信甚至无需系统干预
- 同一进程中的线程切换,不会引起进程切换
- 不同进程中的线程切换,会引起进程切换
- 切换同进程内的线程,系统开销很小
- 切换进程,系统开销较大
注:线程是处理机调度的单位,这里的线程指的是 操作系统看得见的内核级线程,内核级线程是处理机分配的单位 。
同进程的线程之间可以共享进程的代码段、全局变量、打开的文件,不共享线程各自的栈指针等TCB内容
-
线程的实现方式
线程的实现可以分为两类:用户级线程 和 内核级线程。内核级线程又称内核支持的线程。
-
用户级线程
在用户级线程中,有关线程管理(创建、撤销和切换等)的所有工作都由应用程序在用户空间中完成,内核意识不到线程的存在,因此说用户级线程对操作系统透明。
- 用户级线程由应用程序通过线程库实现,所有的线程管理工作都由应用程序负责(包括线程切换)
- 用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。
- 在用户看来,是有多个线程。但是在操作系统内核看来,并意识不到线程的存在。“用户级线程”就是“从用户视角看能看到的线程
若系统中只有用户级线程,则处理机的调度对象是进程
优点:
- 用户级线程的切换在用户空间即可完成,不需要切换到核心态,
- 线程管理的系统开销小,效率高
缺点:
- 当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。
- 多个线程不可在多核处理机上并行运行
-
内核级线程
内核级线程是在内核的支持下运行的,线程管理的所有工作也是在内核空间内实现的。
- 内核级线程的管理工作由操作系统内核完成。
- 线程调度、切换等工作都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。
- 操作系统会为每个内核级线程建立相应的TCB(Thread Control Block,线程控制块)通过TCB对线程进行管理。“内核级线程”就是“从操作系统内核视角看能看到的线程”
优点:
- 当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。
- 多线程可在多核处理机上并行执行。
缺点:
- 一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。
用户级线程 内核级线程 线程的管理工作由谁来完成 由 应用程序 通过线程库实现所有的线程管理工作 ,包括线程切换 线程管理工作由 操作系统内核完成 线程切换是否需要 CPU 变态 用户级线程切换 可以在用户态下即可完成 ,无需操作系统干预 线程调度、切换等工作都由内核负责,因此 内核级线程的切换 必然需要在 核心态 下才能完成。 OS 是否能意识到用户级线程的存在 OS 内核意识不到用户级线程的存在 用户级线程就是从用户视角看能看到的线程 OS 会为每个内核级线程建立相应的 TCB(线程控制块) 通过TCB对线程进行管理 内核级线程就是从操作系统内核视角看能看到的线程 优点 用户级线程的切换在用户空间即可完成, 不需要切换到核心态,线程管理的系统开销小,效率高 当一个线程被阻塞后,其他线程还可以继续执行,并发能力强 多线程可在多核处理机上并行执行 缺点 当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高 因为进程是处理机调度的基本单位,同一进程的多个线程不可在多核处理机上并行运行 一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成 需要切换到核心态,因此线程管理的开销大,效率低,成本高 -
组合方式
有些系统使用组合方式的多线程实现。在组合实现方式中,内核支持多个内核级线程的建立、调度和管理,同时允许用户程序建立、调度和管理用户级线程。
- 一些内核级线程对应多个用户级线程,这是用户级线程通过时分多路复用内核级线程实现的。
- 同一进程中的多个线程可以同时在多处理机上并行执行,
- 且在阻塞一个线程时不需要将整个进程阻塞,
-
线程库
线程库是为程序员提供创建和管理线程的API。实现方式有以下两种。
- ①在用户空间中提供一个没有内核支持的库。这种库的所有代码和数据结构都位于用户空间中。这意味着,调用库内的一个函数只导致用户空间中的一个本地函数的调用。
- ②实现由操作系统直接支持的内核级的一个库。对于这种情况,库内的代码和数据结构位于内核空间。调用库中的一个API函数通常会导致对内核的系统调用。
-
-
多线程模型
-
一对一模型
一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。
- 优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。(内核级线程优点)
- 缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。(内核级线程缺点)
-
多对一模型
多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程。
- 优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高(用户级线程优点)
- 缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行(用户级线程缺点)
-
多对多模型
n用户及线程映射到m个内核级线程(n>=m)。每个用户进程对应m个内核级线程。
克服了多对一模型并发度不高的缺点(一个阻塞全体阻塞),又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。还拥有上述两种模型各自的优点。
-
-
线程的状态与转换
-
线程的组织与控制
-
线程控制块
与进程类似,系统也为每个线程配置一个线程控制块TCB,用于记录控制和管理线程的信息。线程控制块通常包括
- ①线程标识符
- ②一组寄存器,包括程序计数器、状态寄存器和通用寄存器
- ③线程运行状态,用于描述线程正处于何种状态
- ④优先级
- ⑤线程专有存储区,线程切换时用于保存现场等
- ⑥堆栈指针,用于过程调用时保存局部变量及返回地址等。
同一进程中的所有线程都完全共享进程的地址空间和全局变量。
各个线程都可以访问进程地址空间的每个单元,所以一个线程可以读、写或甚至清除另一个线程的堆栈。
-
线程的创建
用户程序启动时,通常仅有一个称为“初始化线程”的线程正在执行,其主要功能是用于创建新线程。
在创建新线程时,需要利用一个线程创建函数,并提供相应的参数,如指向线程主程序的入口指针、堆栈的大小、线程优先级等。线程创建函数执行完后,将返回一个线程标识符。
-
线程的终止
当一个线程完成自己的任务后,或线程在运行中出现异常而要被强制终止时,由终止线程调用相应的函数执行终止操作。
但是有些线程(主要是系统线程)一旦被建立,便一直运行而不会被终止。通常,线程被终止后并不立即释放它所占有的资源,只有当进程中的其他线程执行了分离函数后,被终止线程才与资源分离,此时的资源才能被其他线程利用。
被终止但尚未释放资源的线程仍可被其他线程调用,以使被终止线程重新恢复运行。
-
错题总结:
1.线程包含CPU现场,可以独立执行程序
2.并发进程的运行结果具有不可再现性
3.在单处理器系统中任何时刻都只有一个进程处于运行态(X)所有进程都死锁
4.一个进程在同一时刻不能执行多个程序,只能执行一个程序
5.分时系统中,处于就绪态的进程最多
6.并发进程失去封闭性是指:并发进程共享变量,其执行结果与速度有关
7.进程是资源分配的单位,内核级线程是调度和分派的单位
8.速度最快的进程通信方式:共享内存
9.第27题
10.线程不会增加进程安全性
11.51题A
12.用户级线程切换是咱们自己控制的
13.同一进程的若干线程不能共享某个线程的栈指针
14.管道只允许单向的数据传输
双向传输需要两个管道
15.父子进程不是完全共享父进程虚拟地址空间,只是共享一部分