文章目录
知识框架
进程的基本概念
-
进程
-
进程实体的概念
进程实体又称为进程映像,进程实体由PCB、程序段、数据段组成
进程的管理者(操作系统)所需的数据都存放在PCB中,程序本身的运行所需的数据存放在程序段和数据段中
- 进程控制块(PCB) :记录用于描述进程情况及控制进程运行所需要的全部信息
- 程序段:存放要执行的代码
- 数据段:存放程序运行过程中处理的各种数据
-
进程的概念:进程是进程实体的运行过程,是操作系统进行资源分配和调度的一个独立单位
-
进程的组织方式:链接方式(队列)、索引方式(表)
-
进程的特征
- 动态性:进程是程序的一次执行过程,是动态地产生、变化和消亡的
- 并发性:内存中有多个进程实体,各进程可并发执行
- 独立性:进程是能独立运行、独立获得资源、独立接受调度的基本单位
- 异步性:各进程按各自独立的、不可预知的速度向前推进,操作系统要提供进程同步机制来解决异步问题
- 结构性:每个进程都会配置一个PCB。结构上看,进程由程序段、数据段、PCB组成
-
进程控制与通信
-
进程的七种状态
-
运行:运行所需资源√,CPU√。占有CPU,并在CPU上运行
-
就绪:运行所需资源√,CPU×。具备运行条件,但CPU被占用,暂时不能运行
-
阻塞:运行所需资源×,CPU×。因等待某一事件而暂时不能运行
-
创建:操作系统为新进程分配资源,创建PCB
-
终止:操作系统回收进程的资源,撤销PCB
-
就绪挂起:运行所需资源√。进程映像调入外存等待
-
阻塞挂起:运行所需资源×。进程映像调入外存等待
-
-
进程控制
用原语实现进程控制,即实现进程状态之间的转换
- 原语的类型:创建原语、撤销原语、阻塞原语、唤醒原语、切换原语
- 原语的作用
- 更新PCB中的信息:修改进程状态标志、将运行环境保存到PCB、从PCB恢复运行环境
- 将PCB插入合适的队列
- 分配/回收资源
-
进程通信
进程通信即进程间的信息交换
- 共享存储:基于数据结构、基于存储区
- 消息传递:直接通信方式、间接通信方式
- 管道通信
进程调度
-
处理机调度
-
高级调度(作业调度)
按照某种规则,从外存的后备队列中选择合适的作业将其调入内存,并为其创建进程
-
中级调度(内存调度)
按照某种规则,从外存的挂起队列中选择合适的进程将其数据调回内存
-
低级调度(进程调度)
按照某种规则,从内存的就绪队列中选择一个进程为其分配处理机
-
-
进程调度
-
需要进行进程调度与切换的情况
-
当前运行的进程主动放弃处理机:正常终止、内中断
-
当前运行的进程被动放弃处理机:外中断
-
-
不能进行进程调度与切换的情况
-
处理中断的过程中
-
进程在操作系统内核程序临界区中(在普通临界区中是可以进行调度和切换的)
-
在原子操作过程中(原语)
-
-
进程调度的方式
- 非剥夺调度方式,又称非抢占方式
- 剥夺调度方式,又称抢占方式
-
进程切换的过程
-
对原来运行进程各种数据的保存
-
对新的进程各种数据的恢复
-
-
-
调度算法
- 调度算法的评价指标
- CPU利用率:忙碌时间/总时间
- 系统吞吐量:完成作业量/总时间
- 周转时间
- 周转时间:作业完成时间 - 作业提交时间
- 平均周转时间:各作业周转时间之和/作业数
- 带权周转时间:作业周转时间/作业实际运行时间
- 平均带权周转时间:各作业带权周转时间之和/作业数
- 等待时间:进程或作业等待被服务的时间之和
- 响应时间:从用户提交请求到首次产生响应所用的时间
- 七种调度算法
- 先来先服务(FCFS)
- 短作业优先(SJF)
- 最短剩余时间优先(SRTF)
- 高响应比优先(HRRN)
- 时间片轮转
- 优先级调度
- 多级反馈队列
- 调度算法的评价指标
进程同步与互斥
-
进程同步
有的进程之间需要相互配合地完成工作,各进程的工作推进需要遵循一定的先后顺序。
并发性带来了异步性,因此有时需要通过进程同步解决这种异步问题。
-
进程互斥
临界资源是指一个时间段内只能提供给一个进程访问的资源。对临界资源的访问,需要互斥的进行。即同一时间段内只能允许一个进程访问该资源
- 临界资源访问过程的四个部分
- 进入区:检查是否可进入临界区,若可进入,需要“上锁”(进厕所关门)
- 临界区:访问临界资源的那段代码(拉粑粑)
- 退出区:负责“解锁"(出厕所开门)
- 剩余区:其余代码部分(洗手)
- 遵循的原则
- 空闲让进:临界区空闲时,应允许一个进程访问
- 忙则等待:临界区正在被访问时,其他试图访问的进程需要等待
- 有限等待:要在有限时间内进入临界区,保证不会饥饿
- 让权等待:进不了临界区的进程,要释放处理机,防止忙等
- 实现方法
- 软件方法(PV操作):单标志法、双标志先检查法、双标志后检查法、皮特森算法
- 硬件方法:中断屏蔽、硬件指令(TestAndSet、Swap)
- 临界资源访问过程的四个部分
-
信号量机制
信号量表示某种资源的数量,通过PV原语对信号量进行操作,用于解决进程同步和互斥问题
- 信号量的类型:整型信号量、记录型信号量(包含整型信号量和指向等待队列的指针)
- 信号量解决进程同步和互斥
- 进程同步:设置同步信号量S,初始值为0。在“前操作”之后执行V(S),在“后操作”之前执行P(S)
- 进程互斥:设置互斥信号量S,初始值为该资源的数量,临界区之前执行P(S),临界区之后执行V(S)
- 管程:对信号量机制的封装,相当于一个类
-
经典问题:生产者—消费者问题、多生产者—多消费者问题、读者—写者问题、哲学家进餐问题、吸烟者问题
死锁
-
死锁的概念
各进程互相等待对方手里的资源,导致各进程都阻塞,无法向前推进的现象。
-
死锁产生的必要条件
- 互斥条件:只有对必须互斥使用的资源的争抢才会导致死锁
- 不剥夺条件:进程所获得的资源在未使用完之前,不能由其他进程强行夺走,只能主动释放。
- 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又被其他进程占有,此时请求进程被阻塞,但又对自己已有的资源保持不放。
- 循环等待条件:存在一种进程资源的循环等待链,链中的每一个进程已获得的资源同时被下一个进程所请求。
-
死锁的处理策略
- 死锁预防:设置限制条件,破坏死锁的必要条件
- 死锁避免:在资源的动态分配过程中,用某种方法防止系统进入不安全状态
- 死锁检测:允许死锁,但及时检测出并施加干预
线程的基本概念
-
线程的基本概念:线程是轻量级进程,是进程中的一个实体,是系统独立调度和分派的基本单位
-
线程的引入带来的变化
- 资源分配、调度:进程是资源分配的基本单位,线程是调度的基本单位
- 并发性:增加了并发度
- 系统开销:减少了系统开销
-
线程的属性
-
线程是处理机调度的基本单位,多CPU计算机中,各个线程可占用不同的CPU
-
线程的组成:每个线程都有一个线程ID、线程控制块(TCB)
-
线程的运行状态:线程也有就绪、阻塞、运行三种基本状态
-
线程共享系统资源:线程几乎不拥有系统资源,同一进程内的不同线程间共享该进程的资源
-
线程通信:由于共享内存地址空间,同一进程中的线程间通信甚至无需系统干预
-
线程切换
同一进程中的线程切换,不会引起进程切换;不同进程中的线程切换,会引起进程切换
切换同进程内的线程,系统开销很小;切换进程,系统开销较大
-
-
线程的实现方式
- 用户级线程(协程):对用户不透明,对操作系统透明
- 内核级线程:对操作系统不透明,对用户透明
-
多线程模型
- 多对一模型:多个用户级线程映射到一个内核级线程。每个用户进程只对应一个内核级线程。
- 一对一模型:一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。
- 多对多模型:n个用户级线程映射到m个内核级线程(n>=m)。每个用户进程对应m个内核级线程。
细节理解
程序、进程、进程实体
-
程序与进程实体
程序存放在外存中,当程序运行时会被载入内存。此时程序在内存中被划分为程序段和数据段,同时操作系统还会构建一个PCB来记录信息。
进程实体就是由PCB、程序段、数据段三部分组成,因此可以说:运行的程序在内存中的状态即为进程实体。
-
进程与进程实体
进程是进程实体的运行过程,进程是动态的,而程序和进程实体都是静态的。
严格意义上讲,进程实体和进程是两个概念。但是在一般情况下,我们把进程实体就称为进程。
-
操作系统引入进程的目的使程序能够并发执行
进程控制块(PCB)
-
PCB存储的信息
- 进程描述信息:进程标识符ID、用户标识符ID
- 进程控制和管理信息:进程状态和优先级
- 资源分配清单:程序段指针、数据段指针、其他资源
- 处理机相关信息:各种寄存器的值
-
创建进程,实际上就是创建进程实体中的PCB
撤销进程,实际上就是撤销进程实体中的PCB
PCB是进程存在的唯一标志。
进程的七种状态
-
五状态模型
-
无 ->创建态:首先要创建一个新进程,操作系统为新进程分配资源,创建PCB,在这个过程中,进程处于创建态。
-
创建态 -> 就绪态:进程创建完成后,进入就绪队列,处于就绪态。
-
就绪态 -> 运行态:如果此时CPU空闲,进程被调度,进入运行队列,处于运行态。
-
运行态 -> 就绪态:当进程时间片已到,或CPU被其他优先级更高的进程抢占,进程又会重新回到就绪态。
-
运行态 -> 阻塞态:当进程用系统调用的方式申请系统资源,或请求等待某个事件的发生,则进程处于阻塞态。
-
阻塞态 -> 就绪态:如果申请的资源被分配,或等待的事件发生,进程会重新转为就绪态。
-
运行态 -> 终止态:如果进程运行结束,或运行过程中遇到不可修复的错误(如数组越界或整数除零),进程就会被撤销,处于终止态
注:任何状态下的进程都可以转为终止态,因为可以人工干预直接终止(任务管理器-终止任务)
-
-
七状态模型
引入了虚拟存储技术之后,可将暂时不能运行的进程调至外存等待。等它重新具备了运行条件且内存又稍有空闲时,再重新调入内存。这么做的目的是为了提高内存利用率和系统吞吐量。
暂时调到外存等待的进程状态为挂起状态。值得注意的是,PCB并不会一起调到外存,而是会常驻内存。PCB中会记录进程数据在外存中的存放位置,进程状态等信息,操作系统通过内存中的PCB来保持对各个进程的监控、管理。被挂起的进程PCB会被放到的挂起队列中。
中级调度(内存调度),就是要决定将哪个处于挂起状态的进程重新调入内存。
-
就绪态 <-> 就绪挂起态:处于就绪队列中的进程调至外存等待,就会处于就绪挂起态。如果调回内存,就重新回到就绪态
-
阻塞态 <-> 阻塞挂起态:处于阻塞队列中的进程调至外存等待,就会处于阻塞挂起态。如果调回内存,就重新回到阻塞态
-
阻塞挂起态 -> 就绪挂起态:如果进程所等待的事件出现,此时就会从阻塞挂起态转为就绪挂起态
-
创建态 -> 就绪挂起态:一个新进程创建完毕后,如果出现内存空间不足的情况,会直接挂到外存等待
-
运行态 -> 就绪挂起态:一个进程下处理机后,可能会被直接挂起
-
-
进程状态之间的转换要求一气呵成,不可中断,因此使用原语来进行控制。
-
原语的类型
- 创建原语:无 -> 创建态 -> 就绪态
- 撤销原语:各种状态 -> 终止态 -> 无
- 阻塞原语:运行态 -> 阻塞态
- 唤醒原语:阻塞态 -> 就绪态
- 切换原语:运行态 -> 阻塞态/就绪态;就绪态 -> 运行态
阻塞原语和唤醒原语必须成对出现
进程通信
各进程的内存地址空间相互独立,一个进程不能直接访问其他进程的内存地址空间。
但是进程之间是有信息交换的需求的。为了保证进程间的安全通信,就需要操作系统介入进行协调。
比如从相册中直接分享图片给QQ好友,相册进程与QQ进程之间就必须有信息交换
-
共享存储
内存中设置一块共享空间,两个进程对共享空间的访问必须是互斥的。操作系统只负责提供共享空间和同步互斥工具(如P、V操作)
-
基于数据结构的共享:
共享空间被限制为一个特定的数据结构。这种共享方式速度慢、限制多,是一种低级通信方式
-
基于存储区的共享:
在内存中画出一块共享存储区,数据的形式、存放位置都由进程控制,而不是操作系统。相比之下,这种共享方式速度更快,是一种高级通信方式。
-
-
管道通信
管道是指用于连接读写进程的一个共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的缓冲区。
管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。
对讲机就是一种半双工通信。当A讲的时候,B只能听;当B讲的时候,A只能听。
数据以字符流的形式写入管道,当管道写满时,写进程的write()系统调用将被阻塞,等待读进程将数据取走。当读进程将数据全部取走后,管道变空,此时读进程的read()系统调用将被阻塞。
如果没写满,就不允许读。如果没读空,就不允许写。
数据一旦被读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则可能会有读错数据的情况。
-
消息通信
进程间的数据交换以格式化的消息(Message)为单位。消息包括消息头和消息体。
进程通过操作系统提供的发送消息和接收消息两个原语进行数据交换。
- 直接通信方式:消息直接挂到对方消息缓冲队列上
- 间接通信方式:消息先发送到中间实体(信箱)
调度
-
调度的基本概念
当有一堆任务要处理,但由于资源有限,这些事情没法同时处理。这就需要确定某种规则来决定处理这些任务的顺序,这就是“调度”研究的问题。
-
调度的三个层次
-
高级调度
作业:一系列进程的集合
由于内存空间有限,有时无法将用户提交的作业全部放入内存,因此就需要确定某种规则来决定将作业调入内存的顺序。
高级调度(作业调度):按一定的原则从外存上处于后备队列的作业中挑选一个(或多个)作业,给他们分配内存等必要资源,并建立相应的进程(建立PCB),以使它(们)获得竞争处理机的权利。
高级调度是辅存(外存)与内存之间的调度。每个作业只调入一次,调出一次。作业调入时会建立相应的PCB,作业调出时才撤销PCB。高级调度主要是指调入的问题,因为只有调入的时机需要操作系统来确定,但调出的时机必然是作业运行结束才调出。
-
中级调度
引入了虚拟存储技术之后,可将暂时不能运行的进程调至外存等待。等它重新具备了运行条件且内存又稍有空闲时,再重新调入内存。这么做的目的是为了提高内存利用率和系统吞吐量。
暂时调到外存等待的进程状态为挂起状态。值得注意的是,PCB并不会一起调到外存,而是会常驻内存。PCB中会记录进程数据在外存中的存放位置,进程状态等信息,操作系统通过内存中的PCB来保持对各个进程的监控、管理。被挂起的进程PCB会被放到的挂起队列中。中级调度(内存调度),就是要决定将哪个处于挂起状态的进程重新调入内存。
一个进程可能会被多次调出、调入内存,因此中级调度发生的频率要比高级调度更高。
-
低级调度
低级调度(进程调度),其主要任务是按照某种方法和策略从就绪队列中选取一个进程,将处理机分配给它。
进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度。
进程调度的频率很高,一般几十毫秒一次。
-
-
进程调度
-
狭义的进程调度
从就绪队列中选中一个要运行的进程。(这个进程可以是刚刚被暂停执行的进程,也可能是另一个进程,后一种情况就需要进程切换)
进程切换:一个进程让出处理机,由另一个进程占用处理机的过程。
-
广义的进程调度:包含了选择一个进程和进程切换两个步骤。
-
-
进程调度的方式
-
非剥夺调度方式,又称非抢占方式
只允许进程主动放弃处理机。在运行过程中即便有更紧迫的任务到达,当前进程依然会继续使用处理机,直到该进程终或主动要求进入阻塞态。
实现简单,系统开销小。但是无法及时处理紧急任务,适合于早期的批处理系统
-
剥夺调度方式,又称抢占方式。
当一个进程正在处理机上执行时,如果有一个更重要或更紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给更重要紧迫的那个进程。
可以优先处理更紧急的进程,也可实现让各进程按时间片轮流执行的功能(通过时钟中断)。适合于分时操作系统、实时操作系统
-
-
进程切换:进程切换是有代价的,因此如果过于频繁的进行进程调度、切换,必然会使整个系统的效率降低,使系统大部分时间都花在了进程切换上,而真正用于执行进程的时间减少。
信号量机制与管程
-
信号量与互斥锁
-
互斥锁:进程进入临界区时上的锁就是互斥锁,保证进程访问临界资源的唯一性和排他性,但不限制资源释放后其他线程申请的顺序问题,是无序的
-
信号量:范围更广,不局限于临界资源,对于任何资源都可以设置信号量,可以用来实现进程同步和互斥,保证了有序性。在特殊情况下,信号量与互斥锁可以等同。
-
-
临界资源与临界区:临界资源是资源,临界区是使用临界资源的那段代码
-
管程
相当于一个类,这个类利用信号量机制的原理给进程提供了操作共享资源的函数接口
管程是对信号量机制解决进程同步和互斥问题的一个封装,避免了程序员在编写程序时频繁地采用PV操作
死锁
比如在一座狭窄的桥上,两辆车分别从桥的两端上桥。当两车在桥中间相遇时,左边的车占有左侧的桥,如果要过桥就需要右侧的桥;右边的车占有右侧的桥。如果要过桥就需要左侧的桥。两辆车都占有一定的资源,且都完成过桥的进程都需要对方手中的资源,如果此时没有一方能主动让出手中的资源,就会陷入死锁状态。
死锁产生的四个必要条件,首先是互斥条件,资源必须是互斥资源,如果桥足够宽,那么每一侧的桥面都不是互斥资源,两辆车就可以共同“占有”一侧的桥面。其次是不剥夺条件,一方不能强迫另一方放弃手中的资源,只能等待对方主动放弃。如果其中一辆车是黑社会,强迫另一辆车让出桥,那么也不会发生死锁。然后是请求和保持条件,每一方都拿住自己的资源,并等待别人主动让出资源。如果其中一辆车素质比较高,主动让出桥面,也不会发生死锁。最后是循环等待条件,资源的需求形成了一个闭环,A等待B,B等待C,C等待A。在双方的例子中,左侧的车等待右侧的车,右侧的车等待左侧的车,同样也形成了一个闭环。如果两辆车同向而行,那么后车会等待前车让出前方的桥面,但前车不需要等待后方的桥面,所以也不会发生死锁。
注意!发生死锁时一定有循环等待,但是发生循环等待时未必死锁(循环等待是死锁的必要不充分条件)。如果同类资源数大于1,则即使有循环等待,也未必发生死锁。但如果系统中每类资源都只有一个,那循环等待就是死锁的充分必要条件了
进程与线程
-
引入进程与引入线程的目的
引入进程:更好地描述和管理程序并发执行,提高资源利用率和系统吞吐量
引入线程:减少并发的时空开销,提高并发性能
在多道程序同时运行的背景下,进程之间需要共享系统资源,因此会导致各程序在执行过程中出现相互制约的关系,程序的执行会表现出间断性的特征。这些特征都是在程序的执行过程中发生的,是动态的过程,而传统的程序本身是一组指令的集合,是一个静态的概念,无法描述程序在内存中的执行情况,即我们无法从程序的字面上看出它何时执行、何时停顿,也无法看出它与其他执行程序的关系,因此,程序这个静态概念已不能如实反映程序并发执行过程的特征。为了深刻描述程序动态执行过程的性质乃至更好地支持和管理多道程序的并发执行,人们引入了进程的概念。
-
线程的引入带来的变化
-
资源分配、调度
传统进程机制中,进程既是资源分配的基本单位,又是调度的基本单位
引入线程后,进程是资源分配的基本单位,线程是调度的基本单位。线程本身不拥有系统资源,但可以共享其隶属进程的资源
这里的资源是指除CPU以外的其他系统资源,调度是指分配CPU资源
-
并发性
传统进程机制中,只能进程间并发
引入线程后,进程内部的各线程间也能并发,提升了并发度
-
系统开销
传统的进程间并发,需要切换进程的运行环境,系统开销大
线程间并发,如果是同一进程内的线程切换,则不需要切换进程环境,系统开销小
-
多线程模型
-
广义的线程包括用户级线程和内核级线程,狭义的线程单指内核级线程,用户级线程称为协程
-
用户级线程
用户级线程由应用程序通过线程库实现。
用户级线程的管理工作全部由应用程序负责(包括线程切换)。因此用户级线程切换可以在用户态下即可完成,无需操作系统干预。
在用户看来,是有多个线程。但是在操作系统内核看来,并意识不到线程的存在。(用户级线程对用户不透明,对操作系统透明)可以这样理解,“用户级线程”就是“从用户视角看能看到的线程”
-
内核级线程
内核级线程的管理工作由操作系统内核完成。线程调度、切换等工作都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。
可以这样理解,“内核级线程”就是“从操作系统内核视角看能看到的线程”
操作系统只“看得见”内核级线程,因此只有内核级线程才是处理机分配的单位。
-
-
多线程模型
-
多对一模型
多个用户级线程映射到一个内核级线程。每 个用户进程只对应一个内核级线程。
-
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高
-
缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行
-
-
一对一模型
一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。
-
优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
-
缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。
-
-
多对多模型
n个用户级线程映射到m个内核级线程(n>=m)。每个用户进程对应m个内核级线程。
克服了多对一模型并发度不高的缺点,又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。
-