本文根据王道计算机考研《操作系统》视频整理的操作系统的第二章进程管理相关笔记,视频来源于2.1_1_进程的概念、组成、特征_哔哩哔哩_bilibili
一、进程
1、进程的概念
程序:是静态的,就是个存放在磁盘里的可执行文件,就是一系列的指令集合。
进程(Process):是动态的,是程序的一次执行过程,同一个程序多次执行会对应多个进程,进程是程序实体的运行过程,是系统进行资源分配和调度的一个独立单位
当进程被创建时,操作系统会为该进程分配一个唯一的、不重复的“身份证号”——PID (Process ID,进程ID)
(1)操作系统区分各个进程要记录PID、进程所属用户ID (UID),基本的进程描述信息
(2)记录给进程分配了哪些资源:可用于实现操作系统对资源的管理
(3)记录进程的运行情况:实现操作系统对进程的控制、调度
这些信息都被保存在一个数据结构PCB (Process Control Block)中,即进程控制块,PCB是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收其PCB。
PCB 是给操作系统用的。程序段、数据段是给进程自己用的。
一个进程实体(进程映像)由PCB、程序段、数据段组成,进程是动态的,进程实体 (进程映像) 是静态的。进程实体反应了进程在某一时刻的状态
2、进程的状态与状态的转换
进程创建过程:
创建状态:创建PCB,程序段,数据段
就绪状态:已经具备运行条件,但是没有空闲的CPU,暂时不能运行(CPU X,其它资源√)
运行状态:占有CPU,并在CPU上运行,单核只能一个进程(双核两个)(CPU√,其它资源√)
阻塞状态:等待某个事件的发生,如等待某资源为可用或等待 IO 操作完成,暂时不能运行(CPU X,其它资源X)
终止状态:回收内存,程序段,数据段,撤销PCB
进程状态间的转换:
创建态->就绪态 就绪态->运行态 运行态->就绪态
运行态->终止态(比如数组越界、除0异常)
运行态->阻塞态(主动) 阻塞态->就绪态(被动)
3、进程控制
什么是进程控制?实现各种进程状态转换。
如何实现进程控制?用“原语”实现。原语用关/开中断来实现,原语的执行必须一气呵成,不可中断
原语做的事情:
1、更新PCB中的信息
2、将PCB插入合适的队列
3、分配/回收资源
进程创建原语:
进程终止原语:
进程阻塞和唤醒原语:
进程切换原语:
解决办法:在进程切换时先在PCB中保存这个进程的运行环境(保存一些必要的寄存器信息),当原来的进程再次投入运行时,可以通过PCB恢复它的运行环境
进程运行环境——进程上下文
4、进程间通信(IPC)
是指两个进程进程间通信之间产生数据交互。
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立,为了保证安全,一个进程不能直接访问另一个进程的地址空间。
4.1 共享内存
为避免出错,各个进程对共享空间的访问应该是互斥的。各个进程可使用操作系统内核提供的同步互斥工具(如P、V操作)
基于数据结构的共享:共享空间里只能放一个长度为10的数组。这种共享方式速度慢、限制多,是一种低级通信方式
基于存储区的共享:操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式。
4.2 消息传递
进程间的数据交换以格式化的消息 (Message)为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。
直接通信方式:
间接通信方式:
4.3 管道通信
“管道”是一个特殊的共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的内存缓冲区
管道数据读写为先进先出,而共享内存写入读取是任意的
1.管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。
2.各进程要互斥地访问管道(由操作系统实现)
3.当管道写满时,写进程将阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
4.当管道读空时,读进程将阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
5管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:一个管道允许多个写进程,一个读进程;允许有多个写进程,多个读进程,但系统会让各个读进程轮流从管道中读数据 (Linux 的方案)。
二、线程
1、线程的概念
线程理解为“轻量级进程”。线程是一个基本的CPU执行单元,也是程序执行流的最小单位。引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务。引入线程后,进程只作为除CPU之外的系统资源的分配单元 (如打印机、内存地址空间等都是分配给进程的)
线程的属性:
(1)线程是CPU调度的单位
(2)多CPU计算机中,各个线程可占用不同的CPU
(3)每个线程都有一个线程ID、线程控制块 (TCB)
(4)线程也有就绪、阻塞、2运行三种基本状态
(5)线程几乎不拥有系统资源,同一进程的不同线程间共享进程的资源,由于共享内存地址空间,同一进程中的线程间通信甚至无需系统干预
(6)同一进程中的线程切换,不会引起进程切换,不同进程中的线程切换,会引起进程切换,切换同进程内的线程,系统开销很小,切换进程,系统开销较大。
2、线程的实现方式
2.1.用户级线程(ULT)
从用户视角看能看到的线程
1.用户级线程由应用程序通过线程库实现,所有的线程管理工作都由应用程序负责
2.用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。
3.在用户看来,是有多个线程。但是在操作系统内核看来,并意识不到线程的存在。
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高
缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。
2.2 内核级线程(KLT)
内核支持的线程
由操作系统管理,从操作系统内核视角看能看到的线程
1.内核级线程的管理工作由操作系统内核完成。
2.线程切换都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。
3.操作系统会为每个内核级线程建立相应的TCB (Thread Control Block,线程控制块),通过TCB对线程进行管理。
优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。
2.3 多线程模式
一对一模型:一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。
优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
缺点:一个用户进程会占用多个内核级线程。线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。
多对一模型:多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程。
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高
缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行
多对多模型:n个用户级线程映射到 m 个内核级线程(n >= m)。每个用户进程对应m 个内核级线程。克服了多对一模型并发度不高的缺点 (一个阻塞全体阻塞),又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。
用户级线程是“代码逻辑”的体,内核级线程是“运行机会”的载体
内核级线程才是处理机分配的单位。一段“代码逻辑”只有获得了“运行机会”才能被CPU执行
3.线程的状态与转换
三、处理机调度
1、调度的概念、层次
调度:当有一堆任务要处理,但由于资源有限,这些事情没法同时处理。这就需要确定某种规则来决定处理这些任务的顺序,这就是“调度”研究的问题。
1.高级调度
作业:一个具体的任务
用户向系统提交一个作业=用户让操作系统启动一个程序
按一定的原则从外存的作业后备队列中挑选一个作业调入内存,并创建进程。每个作业只调入一次,调出一次。作业调入时会建立PCB,调出时才撤销PCB。
2.进程调度/低级调度
低级调度 (进程调度/处理机调度) -- 按照某种策略从就绪队列中选取一个进程,将处理机分配给它。进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度进程调度的频率很高,一般几十毫秒一次。
3.中级调度
中级调度(内存调度)——按照某种策略决定将哪个处于挂起状态的进程重新调入内存
内存不够时,可将某些进程的数据调出外存。等内存空闲或者进程需要运行时再重新调入内存。暂时调到外存等待的进程状态为挂起状态。被挂起的进程PCB会被组织成挂起队列
暂时调到外存等待的进程状态为挂起状态
2、调度的时机
进程调度(低级调度):就是按照某种算法从就绪队列中选择一个进程为其分配处理机
需要进行进程调度与切换的情况:
1.当前运行的进程主动放弃处
(1)进程正常终止
(2)运行过程中发生异常而终止
(3)进程主动请求阻寨(如等待I/0)
2.当前运行的进程被动放弃处理
(1)分给进程的时间片用完
(2)有更紧急的事需要处理(如I/0中断)
(3)有更高优先级的进程进入就绪队列
不能进行进程调度与切换的情况:
(1)在处理中断的过程中。中断处理过程复杂,与硬件密切相关,很难做到在中断处理过程中进行进程切换。
(2)进程在操作系统内核程序临界区中。
(3)在原子操作过程中(原语)。原子操作不可中断,要一气呵成
方式:
非剥夺调度方式(非抢占式):只允许进程主动放弃处理机
剥夺调度方式(抢占式):进程被动放弃,可以优先处理紧急任务,适合分时操作系统、实时操作系统
“狭义的进程调度”与“进程切换”的区别:
狭义的进程调度指的是从就绪队列中选中一个要运行的进程。 (这个进程可以是刚刚被暂停执行的进程也可能是另一个进程,后一种情况就需要进程切换)进程切换是指一个进程让出处理机,由另一个进程占用处理机的过程。
广义的进程调度包含了选择一个进程和进程切换两个步骤。
进程切换的过程主要完成了:
1.对原来运行进程各种数据的保存
2.对新的进程各种数据的恢复
(如:程序计数器、程序状态字、各种数据寄存器等处理机现场信息,这些信息一般保存在进程控制块)
3、调度器和调度程序
调度时机:
(1)创建新进程
(2)进程退出
(3)运行进程阻塞
(4)I/0中断发生(可能唤醒某些阻塞进程)
非抢占式调度策略,只有运行进程阻塞或退出才触发调度程序工作
抢占式调度策略,每个时钟中断或k个时钟中断会触发调度程序工作
闲逛进程:调度程序永远的备胎,没有其他就绪进程时,优先级最低,可以是0地址指令占一个完整的指令周期(指令周期末尾例行检查中断),能耗低
4、调度器的评价指标
1、CPU利用率
CPU利用率=CPU忙碌的时间/总时间
2、系统吞吐量
总共完成了多少道作业/总共花了多少时间
3、周转时间
周转时间(提交作业到完成作业花费的时间)
平均周转时间(各作业周转时间之和/作业数)
带权周转时间(作业周转时间/作业实际运行的时间)
平均带权周转时间(各作业带权周转时间/作业数)
4、等待时间
进程或作业等待处理机状态时间的和
进程:等待被服务的时间之和
作业:建立进程后的等待时间+作业在外存后备队列中等待的时间
5、响应时间
从用户提交请求到首次产生响应所用的时间
5、调度算法
5.1 批处理
(1)先来先服务(FCFS)
(2)短作业优先(SJF)
最短(服务时间最短)的作业优先得到服务,时间相同,先到达的先被服务
非抢占式(SJF):选最短需要时间的作业先进入运行态
抢占式(SRTN):有新作业进入就绪队列或有作业完成了,考察队列中的最小需要时间的作业
在所有进程都几乎同时到达时,采用SJP调度算法的平均等待时间、平均周转时间最少
优点:“最短的”平均等待时间,平均周转时间
缺点:对短作业有利,对长作业不利,可能产生饥饿现象
注意:
(3)高响应比优先(HRRN)
5.2 交互式
(1)时间片轮转(RR)————进程调度
如果时间片太大,使得每个进程都可以在一个时间片内就完成,则时间片轮转调度算法退化为先来先服务调度算法,并且会增大进程响应时间。因此时间片不能太大。
另一方面,进程调度、切换是有时间代价的(保存、恢复运行环境),因此如果时间片太小,会导致进程切换过于频繁,系统会花大量的时间来处理进程切换,从而导致实际用于进程执行的时间比例减少。可见时间片也不能太小。
(5)优先级调度
就绪队列未必只有一个,可以按照不同优先级来组织。
另外,也可以把优先级高的进程排在更靠近队头的位置根据优先级是否可以动态改变。
可将优先级分为静态优先级和动态优先级两种
静态优先级:创建进程时确定,之后一直不变。
动态优先级:创建进程时有一个初始值,之后会根据情况动态地调整优先级
(6)多级反馈队列调度算法