2 进程管理
2.1 进程 & 线程
2.1.1 进程的概念和特征
1)概念
程序 | 进程 |
---|---|
静态 | 动态 |
磁盘里的可执行文件,一系列指令的集合 | 一次执行过程。同一个程序多次执行会对应多个程序进程 |
2)进程的组成-PCB(Process Control Block)
但凡管理时所需要的信息,都会被放在PCB中,PCB是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收其PCB。
Q:操作系统如何分辨程序和进程?
A:当进程被创建时,操作系统会为该进分配一个唯一的、不重复的“身份证PID( Process ID,进程ID)
操作系统要记录的内容有:
1)基本的描述信息,帮助操作系统加以区分:PID、进程所属用户ID(UID);
2)可用于实现操作系统对资源的管理:可用于实现操作系统对资源的管理:给进程分配了哪些资源
3)可用于实现操作系统对进程的控制、调度:进程的运行情况
3)特征
2.1.2 进程的状态与转换
1)状态
a)就绪态:当进程创建完成后,便进入“就绪态”, 处于就绪态的进程已经具备运行条件, 但由于没有空闲CPU,就暂时不能运行
b)运行态:进程此时在CPU上运行
c)阻塞态:在进程运行的过程中,可能会请求等待某个事件的发生(如等待某种系统资源的分配,或者等待其他进程的响应)。
在这个事件发生之前,进程无法继续往下执行,此时操作系统会让这个进程下CPU,并让它进入“阻塞态”
d)创建态:正在被创建的状态
e)终止态:个进程可以执行exit系统调用,请求操作系统终止该进程此时该进程会进入“终止态”,操作系统会让该进程下CPU, 并回收内存空间等资源,最后还要回收该进程的PCB。当终止进程的工作完成之后,这个进程就彻底消失了。
2)状态间的转换
3)进程的组织方式
2.1.3 进程控制
简化理解:反正进程控制就是要实现进程状态转换
原语是一种特殊的程序, 它的执行具有原子性。也就是说,这段程序的运行必须一气呵成,不可中断
如何实现进程的原子性?
用只可以一气呵成的原语实现
为何要一气呵成?
如果不能一气呵成,那么控制的过程就会被打断,可能导致操作系统中的某些数据结构信息不统一的情况。
如何实现原语的原子性?
用俩特权指令:开中断&关中断指令
2.1.4 进程的组织
进程的组成 | 进程的组织 |
---|---|
一个进程内部由哪些部分构成 | 多个进程之间的组织方式 |
1)链接方式
按照进程状态将PCB分为多个队列,操作系统持有指向各个队列的指针
2)索引方式
根据进程状态的不同,建立几张索引表,操作系统持有指向各个索引表的指针
2.1.5 进程的通信
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。
为了保证安全,一个进程不能直接访问另个进程的地址空间。
2.1.6 线程概念和多线程模型
什么是线程,为什么要引入线程
线程是一个基本的CPU执行单元, 也是程序执行流的最小单位。引入了“线程”,来增加并发度(进程之间 & 各线程之间)。引入线程后,进程只作为除CPU之外的系统资源的分配单元。线程则作为处理机的分配单元。
2.2 处理机调度
2.2.1 调度的概念
确定某种规则来决定处理这些任务的顺序
高级调度(作业调度)。按一定的原则从外存的作业后备队列中挑选一个作业调入内存,并创建进程。每个作业只调入一次,调出一次。作业调入时会建立PCB,调出时才撤销PCB。
中级调度(内存调度)——按照某种策略决定将哪个处于挂起状态的进程重新调入内存。
一个进程可能会被多次调出、调入内存,因此中级调度发生的频率要比高级调度更高。
低级调度(进程调度/处理机调度)—— 按照某种策略从就绪队列中选取一个进程,将处理机分配给它。
进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度。进程调度的频率很高,一般几十毫秒一次。
2.2.2 调度的时机、切换与过程
2.2.3 进程调度方式
2.2.4 调度的基本准则
2.2.5 典型的调度算法
先来先服务(FCFS) | 短作业优先(SJF) | 高响应优先(HRRN) | 时间片轮转(RR) |
---|---|---|---|
公平的角度 | 最少的平均等待时间,最少的平均周转时间,最少的平均带权周转时间 | 综合考虑作业进程的等待时间和要求服务时间 | 公平轮流地为各个进程服务 |
先来后到 | 服务时间最短的进程先服务 | 选择响应比最高的进程作业先服务 | 每个进程执行一个时间片,如果没有完成则剥夺执行权 |
用于作业时,考虑哪个作业先到后背队列 用于进程调度时,考虑哪个进程先到就绪队列 | 皆可,用于进程时为短进程优先(SPF) | 作业和进程皆可 | 进程调度 |
非抢占式 | 非抢占式; 也有抢占式的版本:最短剩余时间优先算法 | 非抢占式,当前的作业/进程主动放弃才可以进行下一进程 | 抢占式,由时钟来判断是否已到CPU时间 |
公平,算法简单 带权周转时间长,对短作业有利,对长作业不利 | 最短的平均等待时间,平均周转时间 不公平,对短作业有利,对长作业不利,存在饥饿。 | 等待时间相同时,要求服务时间短的优先(SJF的优点) 要求服务时间相同时,等待时间长的优先(FCFS的优点) 避免了长作业饥饿的问题 | 公平;响应快,适用于分时操作系统; 由于高频率的进程切换,因此有一定开销;不区分任务的紧急程度。 |
不会饥饿(某进程/作业长时间得不到服务) | 会饥饿,长作业如果长期得不到服务,则容易饿死 | 不会 | 不会 |
2.3 进程同步
2.3.1 进程同步的基本概念
临界资源:一个时间段内只允许一个进程使用的资源
2.3.2 实现临界区互斥的基本方法
2.3.3 信号量
2.3.4 管程
2.3.5 经典同步问题
-
生产消费问题
实现互斥的P操作一定要在实现同步的P操作之后,否则可能引起“死锁”
两个V操作顺序可以交换
-
多生产者多消费者
缓冲区大于1的时候,会出现覆盖的情况; 因此需要专门设置一个互斥信号mutex
吸烟者问题
轮流让各个吸烟者吸烟”必然需要“轮流的在桌上放上组合一、二、三”,注意体会我们是如何用一个整型变量i实现这个“轮流”过程的; 若一个生产者要生产多种产品(或者说会引发多种前驱事件),那么各个V操作应该放在各自对应的“事件”发生之后的位置
-
读者-写者问题
要求: ①允许多个读者可以同时对文件执行读操作; ②只允许一个写者往文件中写信息; ③任一写者在完成写操作之前不允许其他读者或写者工作; ④写者执行写操作前,应让已有的读者和写者全部退出。
在这种算法中,连续进入的多个读者可以同时读文件;写者和其他进程不能同时访问文件;写者不会饥饿,但也并不是真正的“写优先”,而是相对公平的先来先服务原则。 有的书上把这种算法称为“读写公平法”。
核心思想在于设置了一个计数器 count用来记录当前正在访问共享文件的读进程数 如果需要实现“一气呵成”,自然应该想到用互斥信号量 还要认真体会我们是如何解决“写进程饥饿”问题的
-
哲学家进餐问题
如何防止死锁? 1、可以对哲学家进程施加一些限制条件,比如最多允许四个哲学家同时进餐。这样可以保证至少有一个哲学家是可以拿到左石两只筷子的 2、要求奇数号哲学家先拿左边的镁子,然后再拿石边的子。而偶号哲学家刚好相反。用这种方法可以保证如果相邻的两个奇偶号哲学家都想吃,那么只会有其中一个可以拿起第一只筷子,另一个会直接阻塞。这競避免了占有一支后再等待另一只的情况 3、仅当一个哲学家左右两支筷子都可用时才允许他抓起筷子。 各哲学家拿筷子这件事必须互斥的执行。 每个进程都需要同时持有两个临界资源,因此就有“死锁”问题的隐患
-
2.4 死锁
2.4.1 死锁的概念
2.4.2 死锁的处理策略
避免死锁-银行家算法
为了能对系统是否已发生了死锁进行检测,必须
①用某种数据结构来保存资源的请求和分配信息
②提供一种算法,利用上述信息来检测系统是否已进入死锁状态。