第一章 操作系统概述
1.1.1 操作系统的概念、功能和目标
目前在市场上,我们熟知的操作系统有Window
、安卓
、IOS
、MacOS
、Linux
。那么操作系统的概念到底是什么呢?
如果结合生活经验是理解计算机系统的层次结构的话,我们可以来见证一台电脑的诞生:
- 买一台裸机
- 安装Windows操作系统
- 安装QQ
- 本宝宝使用QQ和朋友尬聊
1.1.1.1 操作系统的概念
用一个图片来概括计算机系统的层次结构的话,如图:
从图上来看,操作系统位于裸机之上,应用程序在操作系统的支持下运作,也就是说,操作系统起到了一个承上启下的作用,如图中所示,它可以负责管理协调硬件、软件等计算机资源的工作,为上层的应用程序、用户提供简单易用的服务。由此我们可以引出操作系统的定义:
操作系统(Operating System , OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口和环境,它是计算机系统中最基本的系统软件。
如果要拿直观的例子来看的话,打开window操作系统的任务管理器,我们就可以理解上面的定义所在:
1.1.1.2 作为系统资源的管理者
现在我们需要思考几个问题:
- 操作系统作为系统资源的管理者,需要提供什么功能?
- 操作系统作为用户和计算机硬件之间的接口,要为其上层的用户、应用程序提供简单易用的服务,需要实现什么功能?
- 操作系统作为最接近硬件的层次,需要在纯硬件的基础上实现什么功能?
在思考这些问题前,我们先补充一个知识——进程。
如果学过数据库我们知道:进程是一个程序的执行过程。执行前需要将改程序放到内存中,才能被CPU处理。
举一个平时上网中最简单的例子,如果我们要用QQ和朋友视频聊天,那么我们在没有快捷方式的情况下,我们做的会是如下步骤:
- 在各个文件夹中找到QQ安装的位置
- 双击打开QQ.exe
- QQ程序正常聊天
- 开始和朋友视频聊天
在这个过程中,在第一步进行的时候,需要找到QQ程序所在的文件夹位置;在第二步进行的时候,需要把该程序相关数据放入内存;在第三步的时候,对应的进程被处理机(CPU)处理;在第四步的时候,需要将对应的摄像头设备分配给进程。所以举这个例子出来后,我们可以看到操作系统作为资源的管理者,他提供了以下四种功能
:
- 处理机管理
- 存储器管理
- 文件管理
- 设备管理
而其目标,就是为了安全、高效
地管理系统的资源。
1.1.1.3 作为用户和计算机硬件之间的接口
自下往上看,操作系统需要提供给应用程序怎样的接口呢?大体可以分为以下三类:
-
命令接口:允许用户
直接使用
-
程序接口:允许用户通过程序
间接使用
-
GUI:现代操作系统中最流行的图形用户接口
其中我们可以把命令接口
和程序接口
统称为用户接口
。在考研中最重要的即为这两个。
命令接口允许用户直接使用,其分类分为两种,一种是联机命令接口,特点是用户说一句系统做一句;另外一种是脱机命令接口,特点是用户说一堆,系统做一堆。
如果体现在windows系统的电脑上,我们可以按下win+R,输入cmd打开shell窗口,这实际上是一个交互式命令接口
,用户说一句,操作系统做一句,这就是联机命令接口。而脱机命令接口又为批处理命令接口
,其在Window中体现为shell脚本。
程序接口在Windows操作系统电脑上的体现有很多,如:C:\windows\System32\user32.dll,如果程序员在程序中调用user.32.dll,即可实现创建窗口等功能,该功能只能通过用户程序间接使用
。
GUI作为图形用户界面,其结构操作更加明了,用户可以使用形象的图形界面进行操作,而不需要记忆复杂的命令、参数。如果举一个例子的话:在Window操作系统中,删除一个文件只需要把文件拖拽进回收站即可。
我们对以上的知识做一个小结:
1.1.1.4 作为最接近硬件的层次
在1.1.1.3中,我们了解了从操作系统到应用程序直接所提供给用户的接口种类;在这一小节,我们会从上往下看,从操作系统到裸机又有什么关联。
我们常说的裸机
,指的是没有任何软件支持的计算机;在裸机上安装的操作系统,可以提供资源管理功能和方便用户的服务功能,将裸机改造成功能更强、使用更方便的机器。
我们通常把覆盖了软件的机器称为扩充机器
,又称为虚拟机
。
1.1.1.5 小结
1.1.2 操作系统的特征
我们接下来讲的时候关于操作系统的四大特征:并发
、共享
、虚拟
、异步
。其中并发和共享是两个最基本的特征,两者互为存在条件。
1.1.2.1 并发
我们说的并发指的是:两个或多个事件在同一时间间隔发生。这些事件宏观上是同时发生的,但微观上是交替发生的。
对于跨考的同学来说,比较容易混淆的就是并行的概念,我们所说的并行通常指的是:指两个或多个事件在同一时刻同时发生。
这里的两个概念容易混淆,我们讲一个例子:
有两个人一个叫小明一个叫小刚。它们每人都有两个女朋友。对于小明来说,他喜欢的是和一号、二号一起出门约会;而对于小刚来说,他喜欢8:00和一号约会,9:00和二号约会,10:00和一号约会。
这里我们发现两个人同样都是在约会,但是小明是同一时刻同时发生,属于并行
;而小刚如果别人问他你怎么约会的,他会说他和两个女生同时约会,但是实际上,它是和两个女生交替约会,这就是宏观和微观的区别,其属于并发
。
回到知识点上来,如果我们说操作系统的并发性
的话,通常指的是计算机系统中同时存在着多个运行着的程序。
一个单核处理器(CPU)同一时刻只能执行一个程序,因此操作系统会负责协调多个程序交替执行;而事实上,操作系统就是伴随着“多道程序技术”而出现的。因此,操作系统和程序并发是一起诞生的。
当今的计算机,一般都是多核CPU、比如Intel的第八代i3处理器就是4核CPU,这意味着同一时刻可以有4个程序并行
执行,但是操作系统的并发性依然必不可少,因为每个人根本不可能说一台电脑只开四个应用程序吧。
1.1.2.2 共享
共享即资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。共享有两种资源共享方式:
- 互斥共享方式
- 同时共享方式
互斥共享方式指的是:系统中的某些资源,虽然可以提供给多个进程使用,但一个时间段内只允许一个进程访问该资源。
而同时共享方式指的是:系统中的某些资源,允许一个时间段内由多个进程“同时”对它们进行访问。
为什么我们这里的同时在打双引号呢?这是因为我们所谓的同时往往是宏观上的,而在微观上,这些进程可能是交替地对该资源进行访问的(即分时共享)。
我们可以用例子来理解以上的概念,互斥共享方式就相当于使用QQ和微信视频,同一时间段内摄像头只能分配给其中一个进程;而同时共享方式就相当于QQ和微信同时发送文件A,宏观上看好像是同时读取并发送,实际上是两个进程交替访问硬盘。当然有时候同时共享方式也有可能真的是同时
,比如说你一边玩游戏开游戏音效一边听歌,这时候两个进程真的是在同时对硬盘上的资源同时访问了。
1.1.2.3 并发和共享的关系
并发性
是指计算机中同时存在着多个运行着的程序;共享性
是指系统中的资源可供内存中多个并发执行的进程共同使用。
如果通过例子来看的话,使用QQ发送文件A,同时使用微信发送文件B,两个进程正在并发执行(并发性),且需要共享地访问硬盘资源(共享性),这就意味着:如果失去并发性,则系统中只有一个程序正在运行,此时共享性失去了存在的意义;如果失去共享性,则QQ和微信不能同时访问硬盘资源,就无法实现同时发送文件,也就无法并发。
1.1.2.4 虚拟
虚拟是指把一个物理上的实体变为若干个逻辑上的对应物。物理实体是实际存在的,但逻辑上的对应物是用户感受到的。
用一个例子来讲述上面的知识点:我们拿GTA5作为我们要说的程序,一个程序需要放入内存并给它分配CPU才能执行,GTA5需要4GB的运行内存,QQ需要256MB的运行内存,迅雷需要256MB的运行内存,网易云音乐需要256MB的运行内存。
我们实际上 在一个运行内存4GB的电脑上能够同时开启上面说的四个进程,可是上面的运行内存远远大于4GB,为什么还能同时开呢?
这就是虚拟存储器技术中的空分复用技术
,实际上只有4GB,在用户看来似乎远远大于4GB。
而如果是在某单核CPU的计算机中,用户打开了以下软件:
这时候我们知道一个程序只能分配给CPU才能执行,那么为什么单核CPU的电脑中能同时运行这么多个程序呢?这也是虚拟处理器技术,其采用了时分复用技术
,微观上处理机在各个微小的时间段内交替着为各个进程服务,实际上只有一个单核CPU,但是用户看起来似乎有6个CPU同时为自己服务一样。
所以综上所述,虚拟技术可以分为空分复用技术(如虚拟存储器技术)和时分复用技术(如虚拟存储器技术)。显然,如果失去了并发性,则一个时间段内系统中只需运行一道程序,那么就失去了实现虚拟性的意义了。因此,没有并发性,就谈不上虚拟性。
1.1.2.5 异步
异步是指,在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。
如果学过数据库的话,实际上你可以把这里的知识点看出是两个事务同时对一个资源做请求,但是这里两个事务最终都会提交,但总是有个先后的,不可能说两个人同时对一个资源同时使用,这样就会出现读写冲突和写写冲突等相关问题。
再举个例子:
与1号2号的约会相当于两个进程的处理,每个进程都有各自需要执行的指令。老渣的心相当于有限的系统资源。由于可分配的资源资源有限,进程的执行不是一贯到底的,而是走走停停的,以不可以预知的速度向前推进。
显然在这里,如果失去了并发性,则系统只能串行地处理各个进程,每个进程的执行会一贯到底。只有系统拥有并发性,才有可能导致异步性。
1.1.2.6 小结
重要考点
- 理解并发和并行的区别
- 并发和共享互为存在条件
- 没有并发和共享,就谈不上虚拟和异步,因此并发和共享是操作系统的两个最基本的特征
1.1.3 操作系统的发展及分类
知识总览
其中绿框部分是考研重点
学习提示:重点理解各阶段的优点和缺点。各阶段的主要优点都是解决了上一阶段的主要缺点。
1.1.3.1 手工操作阶段
手工操作阶段使用的是穿孔纸带技术
,穿孔纸带是利用打孔技术在纸带上打上一系列有规律的孔点,以适应机器的读取和操作,加快工作速度,提升工作效率。是早期向计算机中输入信息的载体。在手工操作阶段,程序员写纸带程序,通过在纸带上扎孔的方式写二进制代码;扎孔了代表1,没扎孔代表0,然后输入给主机处理,处理完再将结果通过纸带的方式输出。
当然显而易见的是,程序员写代码的速度慢,纸带输入处理器的速度也慢,纸带机处理速度快。而且同一个时间段中,一台机器只能服务一个程序员。
所以在手工操作阶段,主要缺点即为:用户独占全机、人机速度矛盾导致资源利用率极低。
1.1.3.2 单道批处理系统
在这个阶段中,人们引入脱机输入/输出技术(用磁带完成),并监督程序负责控制作业的输入、输出。
监督程序是操作系统的雏形,在上面的流程中我们可以发现,为实现对作业的连续处理,需要先把一批作业以脱机方式输入到磁带上,并在系统中配上监督(Monitor),在它的控制下,使这批作业能一个接一个地连续处理。其处理过程是:首先由监督程序将磁带上的第一个作业装入内存,并把运行控制权交给该作业;当该作业处理完成时,又把控制权交还给监督程序,再由监督程序把磁带上的第二个作业调入内存。计算机系统就这样自动地一个作业紧接一个作业地进行处理,直至磁带上的所有作业全部完成,这样便形成了早期的批处理系统。虽然系统对作业的处理是成批进行的,但在内存中始终只保持一道作业,故称为单道批处理系统。
所以在单道批处理系统阶段,优点是:缓解了一定程度的人机速度矛盾,资源利用率有所提升。
而缺点也很明显:内存中仅能有一道程序运行,只有该程序运行结束之后才能调入下一道程序。CPU有大量的时间是在空闲等待I/O完成。资源利用率依然很低。
1.1.3.3 多道批处理系统
多道批处理系统的主要优点是:多道程序并发执行,共享计算机资源。资源利用率大幅提升,CPU和其他资源保持“忙碌”状态,系统吞吐量增大。
而主要缺点也很明显:用户响应时间长,没有人机交互功能(用户提交自己的作业之后就只能等待计算机处理完成,中间不能控制自己的作业执行)
。
这里为什么说资源利用率大幅提升呢?这是因为多道批处理系统采取了并发,此时可以同时处理多道进程,不会出现处理器进入大量闲置时间的状态。
1.1.3.4 分时操作系统
分时操作系统是指计算机以时间片为单位轮流为各个用户/作业服务,各个用户可通过终端与计算机进行交互。
比如时间片是0.01s,那么每个任务轮流执行0.01s,在1s内可能会完成多个任务,给用户的感受就是多个“同时”完成。
分时操作系统解决了人机交互问题,其主要优点为:用户请求可以被即使响应,解决了人机交互问题。允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人的存在。
而主要缺点是:不能优先处理一些紧急任务。操作系统对各个用户/作业都是完全公平的,循环地为每个用户/作业服务一个时间片,不区分任务的紧急性
。为此,后来又开发出了实时操作系统
。
1.1.3.5 实时操作系统
实时操作系统主要优点就是能够优先响应一些紧急任务,某些紧急任务不需时间片排队。在实时操作系统的控制下,计算机系统接收到外部信号后及时进行处理,并且要严格的时限内处理完事件。实时操作系统的主要特点是及时性
和可靠性
。
实时操作系统分为两大类:硬实时系统
和软实时系统
。硬实时系统必须在绝对严格的规定时间内完成处理,例如导弹控制系统、自动驾驶系统。而软实时系统能接受偶尔违反时间规定,如12306火车订票系统,偶尔没有及时更新火车票的信息也没什么问题。
1.1.3.6 其他几种操作系统
网络操作系统:是伴随着计算机网络的发展而诞生的,能把网络中各个计算机有机地结合起来,实现数据传送等功能,实现网络中各种资源的共享(如文件共享)和各个计算机之间的通信。
分布式操作系统:主要特点就是分布性和并行性。系统中的各台计算机地位相同,任何工作都可以分布在这些计算机上,由它们并行,协同完成这个任务。
个人计算机系统:如WindowXP、MacOS,方便个人使用。
1.1.3.7 小结
1.1.4 操作系统的运行机制和体系结构
知识总览
预备知识:什么是指令
指令和我们平时所的代码有什么区别呢?
如果拿C语言来说,当我们写好了C语言代码
的时候,编译器会对代码进行编译,编译完会生成机器语言指令
,且在这个过程中,一条高级语言的代码翻译过来可能会对应多条指令。
所以简单来说,指令
就是处理器(CPU)能识别、执行的最基本的命令,例如加法指令就是让处理器执行加法运算。
1.1.4.1 两种指令、两种处理器状态、两种程序
经过上面的介绍后,我们知道了指令是干什么的,但是我们也能发现一些问题:有些指令能让处理器干些比较简单的事,比如加减乘除,这种事情通常无关紧要人畜无害;但是有些指令能让处理器“自毁”呢?系统所有东西都删掉呢?比如内存清零指令
,如果用户程序可以使用这个指令,就意味着一个用户可以将其他用户的内存数据随意清零,这样做显然是很危险的。
所以综上所述,我们把指令分为两类:特权指令
和非特权指令
。前面说的加减乘除这类普通的运算指令即为非特权指令,而内存清零指令就是特权指令;特权指令一般不允许普通用户使用。
那么处理器怎么判别当前是否可以执行特权指令呢?
这就要说到两种处理器状态了:用户态(目态)
和核心态(管态)
。如果此时处理器处于目态,那么CPU只能执行非特权指令,而如果处理器处于管态,那么两种指令它都能执行。
根据能执行指令的程度,我们把程序也划分为两类:内核程序
和应用程序
。操作系统的内核程序是系统的管理者
,既可以执行特权指令,也可以执行非特权指令,运行在核心态,而应用程序为了保证系统能安全运行,它们运行在用户态。
做一个小结,如图所示:
说完这么多,操作系统中的哪些功能应该由内核程序实现呢?
1.1.4.2 操作系统的内核
我们平常说的内核
,实际上指的是计算机的底层软件。结合生活经验来看,我们安装完Windows操作系统后,会发现操作系统提供了多种多样的功能,比如“记事本”、“任务管理器”。然而,操作系统少了这些功能并不会掉一块肉的,顶多是不方便而已。所以结合这些,我们可以回到前面讲的结构图。
在操作系统的结构层次中,实际上包含了内核和非内核,内核中包含了计算机必备的一些组件,比如时钟管理,中断处理,访问原语等,这些都是计算机必不可少的。像进程管理、存储器管理、设备管理等这些和计算机资源管理相关的也是属于内核的一部分。
所以操作系统的内核,指的是:计算机上配置的底层软件,是操作系统最基本、最核心的部分
。实现操作系统内核功能的那些程序就是内核程序。
由于我们前面也说过,任务管理器不是必须的,这也侧面说明了管理并不是必须的,因系统而异;所以对于不一样的系统,有的系统认为资源管理这一部分属于内核功能,而有的则不这么认为。所以,我们通常把那些包含了资源管理这一部分的内核叫做大内核
,而不包含资源管理这一部分的内核叫做微内核
。
1.1.4.3 操作系统的体系结构
大内核和微内核共同组成了操作系统的体系结构。整理一下上面说的,我们可以总结如下:
举个例子:我们可以把操作系统的体系结构问题与企业的管理问题很相似。我们可以把内核比作企业的管理层,负责企业内部一些重要的工作。只有管理层才能执行特权指令,普通员工只能执行非特权指令。用户态、核心态之间的切换相当于普通员工和管理层之间的工作交接。
而大内核就好比企业创立之初,大事小事管理层的人都会经手,虽然做事效率快,管理层不需要和其他人交接工作,直接就可以行使重要权限干重要的事,但是由于分工不明确,人数过少,所以组织结构混乱,难以维护。难以维护可以体现在管理层两个大老板。两个大老板都有采购功能,但是两个人同时采购,一旦出了采购问题就不知道把问题归在谁身上了。
而微内核就好比成熟的企业,管理层只负责一些最核心的工作,组织结构清晰,方便维护,但是这样的话普通员工一有重要的事就要汇报上级审批,效率低下。
1.1.4.4 小结
- 大内核和微内核的优缺点可能作为选择题考查
- 核心态比较重要
1.1.5 中断和异常
知识总览
1.1.5.1 中断机制的诞生
在早期的计算机中,程序只能在计算机中串行执行,如图:
后一道程序常常得等前一道程序执行完,才能开始下一道。这样的话,由于各程序只能串行执行,系统资源利用率低。
为了解决上述问题,人们发明了操作系统,引入中断机制,实现了多道程序并发执行。随即,时代进入了多道批处理阶段。
那么中断机制是什么呢?有什么用处呢?在开展下面的讲解之前,我们先要知道中断的本质,即:发生中断就意味着需要操作系统介入,开展管理工作。
如下面的例子:
当并发执行的程序中,有些程序需要完成从用户态到核心态之间的切换。那么在CPU收到计时部件发出的中断信号后,操作系统此刻就会介入,完成程序由用户态转为核心态的过程。
所以用上述的例子,你可以简单理解为中断的意思就是:到点了,用现在比较流行的梗就是:三点啦,饮茶先啦!
1.1.5.2 中断的概念和作用
经过前面的讲解,我们大概可以知道这么几件事。
- 当中断发生时,CPU立刻进入核心态。
- 当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进行处理。
- 对于不同的中断信号,会进行不同的处理。
发生了中断,就意味着需要操作系统介入,开展管理工作。由于操作系统的管理工作(比如进程切换,分配I/O设备等)需要使用特权指令,因此CPU要从用户态转为核心态。中断可以使CPU从用户态切换为核心态,使操作系统获得计算机的控制权。有了中断,才能实现多道程序并发执行。
所以用户态和核心态是如何实现相互切换的呢?
用户态→核心态的过程中,是通过中断实现的,而且中断是实现的唯一方法。
而核心态→用户态的过程,是通过执行一个特权指令,将程序状态字(PSW)的标志位设置为“用户态”。
1.1.5.3 中断的分类
中断大体可以分为两类:内中断和外中断,外中断一般也叫做“中断”,但是是狭义中断;而我们提到的所有中断是广义上的中断。
如图所示:
内中断和外中断是根据CPU的内外部来判断的,如果和当前执行的指令有关,说明是在CPU内部发生的,属于内中断;而如果和当前执行的指令无关,说明是在CPU外部发生的,属于外中断。
在考试中,主要是给出一个事件,要我们判断属于哪类中断,至于具体的情况,只作为了解。
此外,内中断还有一种分类方式,这里也给出示意图,大家可以自行学习。
1.1.5.4 小结
- 中断的概念和作用
- 中断的分类
1.1.6 系统调用
知识总览
1.1.6.1 系统调用和作用
前面我们在1.1.1.3那里讲过操作系统作为用户和计算机硬件之间的接口,它需要向上提供一些简单易用的服务。主要包括命令接口和程序接口。那时候我们说过程序接口
主要是允许用户间接调用。实际上,程序接口由一组系统调用
组成。
系统调用是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以发出系统调用
请求来获得操作系统的服务。
那为什么应用程序要给操作系统发出请求呢,为什么操作系统需要提供给“系统调用”功能呢?
让我们想象一个场景,如果我们去打印店打印论文,当我按下了“打印”之后,打印机开始工作。结果我的论文打印到一半的时候,另外一位同学也按下“打印”,开始打印它自己的论文。最终,你的论文和该同学的论文页面并没有混杂在一起,都是按顺序依次打印的。
那为什么是按顺序依次打印呢?为什么不会乱呢?
体现到我们的操作系统来的话,操作系统就是作为调控的那一部分。在某个时刻多个进程同时向操作系统提出系统调用的请求的时候,操作系统就会对各个请求进行协调管理。
应用程序通过系统调用请求操作系统的服务。系统中的各种共享资源都由操作系统统一掌管,因此在用户程序中,凡是与资源有关的操作,都必须通过系统调用的方式向操作系统提出服务请求,由操作系统代为完成。这样可以保证系统的稳定性和安全性
,防止用户进行非法操作。
系统调用可以分为五大类,这里只需要简单的了解,在后面我们会详细地介绍他们。
需要注意的是,系统调用相关处理涉及到对系统资源的管理、对进程的控制,这些功能需要执行一些特权指令
才能完成,因此系统调用的相关处理
需要在核心态
下完成。
1.1.6.2 系统调用和库函数
在上图中,有些库函数涉及系统调用,例如“创建一个新文件”;有些库函数则不涉及系统调用,例如“取绝对值”。
1.1.6.3 系统调用背后的过程
在我们用高级语言编写的代码中,若有关于系统调用的函数,我们假设为write()。那么在高级语言编译后会变成汇编语言,如下图:
也就是说,实际上高级语言中的库函数里面有些库函数拥有系统调用的功能,此刻它们虽然看起来很简单,实际上背后蕴含了很多关于系统调用的细节,而高级语言库函数的好用之处在于,它屏蔽了关于底层的细节,给了我们一种系统调用最简单的方式。
这个过程实际上是以下的步骤:
- 首先由传递系统调用参数
- 执行陷入指令(用户态)
- 执行系统调用相应服务程序(核心态)
- 返回用户程序
这里有几个需要注意的点是:
- 陷入指令是在用户态执行的,执行陷入指令之后会立即引发一个内中断,从而CPU进入核心态。
- 发出系统调用请求是在核心态,而对系统调用的相应处理在核心态下进行。
陷入指令
是唯一一个只能在用户态执行,而不可在核心态执行的指令。
1.1.6.4 小结
- 陷入指令也叫做
trap指令
/访管指令
。
第二章 进程
2.1.1 进程的定义、组成、组织方式和特征
知识总览
2.1.1.1 进程的定义
在讲述进程之前,我们首先要了解一个概念:程序
。
程序实际上就是一个指令序列;早期的计算机那时候只支持单道程序,也就是说,在一个程序传入内存的时候,CPU供他使用,内存供他使用,I/O设备也供他使用。
在这个阶段中,内存属于某一个程序。内存中存放的东西分为两类:一种是
程序段
,一种是数据段
;程序段就是这个程序的代码,而程序里所包含的数据就处于数据段内(如变量、常量)。
引入多道程序技术后;同一时刻内内存中可以放入多道程序,各个程序中的代码、运算程序存放的位置不同。操作系统如果想要在内存中找到各程序的存放位置,那就需要引进
进程
的概念了。
为了方便操作系统管理,完成各程序并发执行,人们引入了进程、进程实体的概念。系统为每个运行的程序配置一个数据结构,称为进程控制块(PCB)
,用来描述进程的各种信息(如程序代码的存放位置)。
2.1.1.2 进程的定义
程序段、数据段、PCB三部分组成了进程实体(进程映像)
。一般情况下,我们把进程实体就简称为进程
;所谓创建进程,实质上就是创建进程实体中的PCB;而撤销进程,实质上就是撤销进程实体中的PCB。也就是说,PCB是进程存在的唯一标志。
从不同的角度,进程可以有不同的定义,比较传统典型的定义有:
- 进程是程序的一次执行过程。
- 进程是一个程序及其数据在处理机上顺序执行时
所发生的活动
。 - 进程是具有独立功能的程序在数据集合上
运行的过程
,它是系统进行资源分配和调度的一个独立单位。
三个定义无不在反映一件事:进程是动态的。
引入进程实体的概念后,我把可以把进程定义为:进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。严格来说,进程和进程实体并不一样,进程实体是静态的,而进程是动态的。除非题目专门考查二者区别,否则我们通常认为进程实体就是进程。因此我们也可以说“进程是由程序段、数据段、PCB三部分组成。”
2.1.1.3 进程的组成
从内存的视角来看,进程由如图所示的三部分组成:
从PCB的角度看,PCB由如图所示的结构构成:
- 进程标识符PID用于进程创建时,操作系统用区分不同的进程,其类似于身份证号。当进程被创建的时候,操作系统就会为该进程分配一个唯一的、不重复的ID。
- 用户标识符UID用于标识进程所属的用户是谁。
- 其余的东西后面会细讲这里不多说。
- 处理器相关信息主要是指一些寄存器的值。当进程切换时,我们需要把
进程当前的运行情况
记录下来保存在PCB中,比如程序计数器的值表示了当前程序执行到哪一句。
从进程的组成来看:
2.1.1.4 进程的组织
在一个系统中,通常有数十、数百乃至数千个PCB。为了对他们加以有效的管理,应当用适当的方式把这些PCB组织起来。
需要注意的是,进程的组成讨论的是一个进程内部由哪些部分构成的问题,而进程的组织讨论的是多个进程之间的组织方式问题。
从进程的组织方式来看,分为两类,分别如下:
2.1.1.5 链接方式
链接方式的工作流程如下图,这里不过多赘述。
2.1.1.6 索引方式
索引方式的工作流程如下图,这里不过多赘述。
2.1.1.7 进程的特征
进程和程序是两个截然不同的概念,相比于程序,进程拥有以下特征:
2.1.1.8 小结
2.1.2 进程的状态和转换
知识总览
2.1.2.1 三种基本状态
进程是程序的一次执行。在这个执行过程中,有时进程正在被CPU处理,有时又需要等待CPU服务,可见,进程的状态是会有各种变化。为了方便对各个进程的管理,操作系统需要将进程合理地划分为几种系统。
状态 | 说明 | 补充 |
---|---|---|
运行态 | 占有CPU,并在CPU上运行 | 单核处理机环境下,每一时刻最多只有一个进程处于运行态。(双核环境下可以同时有两个进程处于运行态) |
就绪态 | 已经具备运行条件,但是没有空闲CPU,而暂时不能运行 | 进程已经拥有了除处理机之外所有需要的资源,一旦获得处理机,即可立即进行运行态开始运行。 |
阻塞态(等待态) | 因等待某一事件而暂时不能运行 | 如:等待操作系统分配打印机、等待读磁盘操作的结果。CPU是计算机中最昂贵的部件,为了提高CPU的利用率,需要先将其他进程需要的资源分配到位,才能得到CPU的服务。 |
2.1.2.2 另外两种状态
状态 | 说明 |
---|---|
创建态(新建态) | 进程正在被创建,操作系统为进程分配资源、初始化PCB。 |
终止态(结束态) | 进程正在从系统中撤销,操作系统会回收进程拥有的资源、撤销PCB。 |
2.1.2.3 进程状态的转换
2.1.2.4 小结
绿色框框部分是考研重点
2.1.3 进程控制
知识总览
2.1.3.1 进程控制的过程
进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。
如果是简单理解的话就是:进程控制就是实现进程状态转换。
如果一个进程处于
创建态
,那么他需要初始化PCB、分配系统资源。当所有东西分配结束后,此时创建态变为就绪态
,转变的过程实际上是修改PCB内容和相应的队列,此时该进程的PCB被放入了就绪队列中。当处于就绪态的进程想要转换为
运行态
,那么需要恢复进程运行的环境并且修改PCB内容和相应队列。之所以要恢复进程运行的环境是因为这个进程的上一次运行可能出现意外退出这种情况。当处于运行态的进程想要转换为
阻塞态
,需要保存进程运行环境,并且修改PCB内容和相应的队列。当处于阻塞态,说明是等待资源问题或者是其他进程的等待问题。所以当转换为
就绪态
时,需要修改PCB内容和相应队列。如果等待的是资源,则还需为进程分配系统资源。运行态转换为就绪态的时候,需要保存进程运行环境,并且修改PCB内容和相应队列。
如果运行态转换为
终止态
的时候,需要回收进程拥有的资源,撤销PCB。
2.1.3.1 实现进程控制
用原语
实现进程控制。原语的特点是执行期间不允许中断,只能一气呵成。这种不可被中断的操作即原子操作
。
原语采用关中断指令
和开中断指令
实现。当要用原语实现进程控制时,此时执行关中断指令,如果有外部中断信号要中断进程是会被忽略掉的;而在执行完原语代码后,就会执行开中断指令,如果这时候有外部中断信号就不会被忽略。
显然,关/开中断指令的权限非常大,必然是只允许在核心态下执行的特权指令。
2.1.3.2 进程控制相关的原语
进程控制会导致进程状态的转换。无论哪个原语,要做的无非三类事情:
- 更新PCB中的信息(如修改进程状态标志、将允许环境保存到PCB、从PCB恢复允许环境)
- 所有的进程控制原语一定都会修改进程状态标志
- 剥夺当前运行进程的CPU使用权必然需要保存其运行环境
- 某进程开始运行前必然要恢复其运行环境
- 将PCB插入合适的队列
- 分配/回收资源
进程的创建
状态历程:无→创建态→就绪态
创建原语分为以下的工作:
- 申请空白PCB
- 为新进程分配所需资源
- 初始化PCB
- 将PCB插入就绪队列
引起进程创建的事件有:
事件 说明 用户登录 分时系统中,用户登录成功,系统会为其建立一个新的进程 作业调度 多道批处理系统中,有新的作业放入内存时,会为其建立一个新的进程 提供服务 用户向操作系统提出某些请求时,会新建一个进程处理该请求 应用请求 由用户进程主动请求创建一个子进程
进程的终止
状态历程:就绪态/阻塞态/运行态→终止态→无
撤销原语分为以下的工作:
- 从PCB集合中找到终止进程的PCB
- 若进程正在运行,立即剥夺CPU,将CPU分配给其他进程
- 终止其所有子进程
- 将该进程拥有的所有资源归还给父进程或操作系统
- 删除PCB
引起进程终止的事件有:
- 正常结束
- 异常结束
- 外界干预
进程的阻塞
状态历程:运行态→阻塞态
阻塞原语分为以下的工作:
- 找到要阻塞的进程对于的PCB
- 保护进程运行现场,将PCB状态信息设置为“阻塞态”,暂时停止进程运行
- 将PCB插入相应时间的等待队列
引起进程阻塞的事件有:
- 需要等待系统分配某种资源
- 需要等待相互合作的其他进程完成工作
进程的唤醒
状态历程:阻塞态→就绪态
唤醒原语分为以下的工作:
- 在事件等待队列中找到PCB
- 将PCB从等待队列移除,设置进程为就绪态
- 将PCB插入就绪队列,等待被调度
引起进程唤醒的事件有:
- 等待的事件发生(因何事阻塞,就应由何事唤醒)
进程的切换
状态历程:运行态→阻塞态/就绪态 就绪态→运行态
切换原语分为以下的工作:
- 将运行环境信息存入PCB
- PCB移入相应队列
- 选择另一个进程执行,并更新其PCB
- 根据PCB恢复新进程所需的运行环境
引起进程切换的事件有:
- 当前进程时间片到了
- 有更高优先级的进程到达
- 当前进程主动阻塞
- 当前进程终止
2.1.3.3 小结
2.1.4 进程通信
知识总览
2.1.4.1 什么是进程通信
顾名思义,进程通信就是指进程之间的信息交换。
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。
为了保证安全,一个进程不能直接访问另一个进程的地址空间。
但是进程之间的信息交换又是必须实现的,为了保证进程之间的安全通信,操作系统提供了一些方法。
2.1.4.2 共享存储
使用共享存储的方式进行进程通信的话,操作系统会在内存中开辟一个共享空间,让两个进程进行通信。
需要注意的是:两个进程对共享空间的访问必须是互斥的(互斥访问通过操作系统提供的工具实现);并且操作系统只负责提供共享空间和同步互斥工具(如P、V操作)
共享存储可以分为两种:一种是基于数据结构的共享
,一种是基于存储区的共享
。
基于数据结构的共享:比如共享空间里只能放一个长度为10的数组。这种共享方式速度慢、限制多,是一种低级通信
方式。
基于存储区的共享:在内存中画出一块共享在存储区、数据的形式、存放位置都由进程控制,而不是操作系统。相比之下,这种共享方式速度更快,是一种高级通信方式。
2.1.4.3 管道通信
管道是指用于连接读写进程的一个共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的缓冲区。
需要知道的是:
- 管道只能采用半双工通信,某一个时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。
- 各进程要互斥地访问管道
- 数据以字符流的形式写入管道,当管道写满时,写进程的write()系统调用将被阻塞,等待读进程将数据取走。当读进程将数据全部取走后,管道变空,此时读进程的read()系统调用将被阻塞。
- 如果没写满,就不允许读;如果没读空,就不允许写。
- 数据一旦被读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则可能会有读错数据的情况。
2.1.4.4 消息传递
进程间的数据交换以格式化的消息
为单位。进程通过操作系统提供的“发送消息/接受消息”两个原语进行数据交换。
一个格式化的消息可以分为消息头
和消息体
。消息头包括:发送进程ID、接受进程ID、消息类型、消息长度等格式化的信息(计算机网络中发送的“报文”其实就是一种格式化的消息)。
消息传递也分为两种方式:
通信方式 | 详情 |
---|---|
直接通信方式 | 消息直接挂到接受进程的消息缓冲队列上 |
间接通信方式 | 消息要先发送到中间实体(信箱)中,因此也称为“信箱通信方式”。如:计网中的电子邮件系统。 |
两种方式如图所示:
2.1.4.5 小结
2.1.5 线程概念与多线程模型
2.1.5.1 线程的来源
在很久以前还没有引入进程
之前,系统中的各个程序只能串行执行。比如你想要边听歌边开QQ,这是不可能做到的,只能先做一件事再做一件事。
后来引入进程后,系统中的各个程序可以并发执行。也就是说,可以同时听歌和开QQ。但是,即使引入了进程,也不能在QQ中同时视频聊天和传输文件。这是因为操作系统每一次执行都是按照进程为单位来执行的。
从上面的例子来看,进程是程序的一次执行。但是这些功能显然不可能是由一个程序顺序处理就能实现的。
有的进程可能需要“同时做很多事”,而传统的进程只能串行地执行一系列程序。为此,引入了线程
来提高并发度。
在传统中,进程是程序执行流的最小单位,也就是说,CPU每次执行任务,最少执行一个进程。而后在现在,CPU每次执行任务,最少执行一个线程,线程是进程的子集。也就是说,引入线程后,线程成为了程序执行流的最小单位。
综上所述,我们可以把线程理解为“轻量级进程”。线程
是一个基本的CPU执行单元
,也是程序执行流的最小单位
。引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务(如QQ视频、文字聊天、传文件)。引入线程后,进程只作为除CPU之外的系统资源的分配单元(如打印机、内存地址空间等都是分配给进程的)。
2.1.5.2 线程机制带来的变化
资源分配、调度 | 并发性 | 系统开销 |
---|---|---|
传统进程机制中,进程是资源分配、调度的基本单位 | 传统进程机制中,只能进程间并发 | 传统的进程间并发,需要切换进程的运行环境,系统开销很大。 |
引入线程后,进程是资源分配的基本单位,线程是调度的基本单位 | 引入线程后,各线程间也能并发,提高了并发度 | 线程间并发,如果是同一进程内的线程切换,则不需要切换进程环境,系统开销小,也就是说引入线程后,并发所带来的系统开销减小。 |
切换进程环境的类比:
去图书馆看书。
切换进程运行环境 = 有一个不认识的人要用桌子,你需要把你的书(运行环境)收走,他把自己的书(运行环境)放到桌上。
同一进程内的线程切换 = 你的舍友要用到这张书桌,可以不把桌子上的书收走,因为大家彼此认识(属于同一个进程)。
2.1.5.3 线程的属性
2.1.5.4 线程的实现方式
用户级线程由应用程序通过线程库实现。所有的线程管理工作都由应用程序负责(包括线程切换)。用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。在用户看来,是有多个线程;但是对于操作系统内核来说,并意识不到线程的存在。即用户级线程对用户不透明,对操作系统透明。
内核级线程(Kernel-Level Thread,KTL,又称为“内核支持的线程”)
内核级线程的管理工作由操作系统内核完成。线程调度、切换等工作都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。
在同时支持用户级线程和内核级线程的系统中,可采用两者组合的方式:将n个用户级线程映射到m个内核级线程上(n>=m)
需要重点关注的是:操作系统只“看得见”内核级线程,因此只有内核级线程才是处理机分配的单位
。
拿上面的映射图来说,该进程由两个内核级线程和三个用户级线程构成,在用户看来,这个进程中有三个线程。但即使该进程在一个4核处理机的计算机上运行,也最多只能被分配到两个核,最多只能有两个用户线程并行执行。
2.1.5.5 多线程模型
在同时支持用户级线程和内核级线程的系统中,由几个用户级线程映射到几个内核级线程的问题引出了“多线程模型”问题。
多对一模型
多个用户及线程映射到一个内核级线程。每个用户进程只对应一个内核级线程。
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高。
缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。
一对一模型
一个用户及线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。
优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强,多线程可在多核处理机上并行执行。
缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。
多对多模型
n用户线程映射到m个内核级线程(n>=m)。每个用户进程对于m个内核级线程。
其克服了多对一模型和一对多模型的缺点。
2.1.5.6 小结
这一小节的知识点易作为选择题考查。
2.1.6 处理机调度的概念和层次
知识总览
2.1.6.1 调度的基本概念
实际上,这里要讲的调度和数据库笔记中9.6并发控制的正确性原则中的调度是一个概念。
假设我们现在有这么两个场景:
场景一是用户到银行取钱,普通用户先到先服务,VIP用户可以优先被服务。场景二是上厕所,根据上厕所时长的不一样,每个人私下协商,使用时间短的先进去厕所,使用时间相同的按排队的优先级来使用。
当有一堆任务要处理,但由于资源有限,这些事情没法同时处理。这就需要确定某种规则来决定处理这些任务的顺序,这就是“调度”研究的问题。
在多道程序系统中,进程的数量往往是多于处理机的个数的,这样不可能同时并行地处理各个进程。处理机调度,就是从就绪队列中按照一定的算法选择一个进程并将处理机分配给它运行,以实现进程的并发执行。
2.1.6.2 高级调度
由于内存空间有限,有时无法将用户提交的作业全部放入内存,因此就需要确定某种规划来决定将作业调入内存的顺序。
高级调度(作业调度),即按一定的原则从外存上处于后备队列的作业中挑选一个或多个作业,给他们分配内存等必要资源,并建立相应的进程(建立PCB),以使它们获得竞争处理机的权利。
高级调度是辅存(外存)与内存之间的调度。每个作业只调入一次,调出一次
。作业调入时会建立相应的PCB,作业调出时才撤销PCB。高级调度主要是指调入的问题,因为只有调入的时机需要操作系统来确定,但调出的时机必然是作业运行状态结束才调出。
2.1.6.3 中级调度
在后面,我们将会讲到虚拟存储技术
,这里先暂时提及一下。
在引入了虚拟存储技术后,可将暂时不能运行的进程调至外存等待。等他重新具备了运行条件且内存又稍有空闲时,再重新调入内存。
这么做的目的是为了提高内存利用率
和系统吞吐量
。
暂时调到外存等待的进程状态为挂起状态。值得一提的是,PCB并不会一起调到外存,而是会常驻内存,PCB中会记录数据在外存中的存放位置,进程状态等信息,操作系统通过内存中的PCB来保持对各个进程的监控、管理、被挂起的进程PCB会被放到挂起队列
中。
中级调度(内存调度),就是要决定将哪个处于挂起状态的进程重新调入内存。
一个进程可能会被多次调出、调入内存,因此中级调度发生的频率要比高级调度要高。
2.1.6.4 进程的挂起态和七状态模型
在2.1.2.1 和 2.1.2.2 中我们学习了进程的五状态模型,而这是408要求掌握的;但是在一些自主命题的学校,它们会考查七状态模型
。
暂时调到外存等待的进程状态为挂起状态。挂起态又可以进一步细分为就绪挂起
、阻塞挂起
两种状态。
实际上说白了就是,内存不够用了,满了,先把一些进程挂起放在外存,其PCB放在内存,一旦内存有多余位置了立马把外存中的进程调进来。
这里要注意的是挂起
和阻塞
的区别。两种状态都是暂时不能获得CPU的服务,但挂起态是将进程映像调到外存去了,而阻塞态进程映像还在内存中。有的操作系统会把就绪挂起、阻塞挂起分为两个挂起队列,甚至会根据阻塞原因不同再把阻塞挂起进程进一步细分为多个队列。
2.1.6.5 低级调度
低级调度(进程调度),其主要任务是按照某种方法和策略从就绪队列中选取一个进程,将处理机分配给它。
进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度。
进程调度的频率很高,一般几十毫秒一次。
2.1.6.6 三层调度的联系、对比
2.1.6.7 小结
一般来说,考查的重点并不会是什么高级调度、中级调度、低级调度,而是考它另一个名字:作业调度、内存调度、进程调度。
2.1.7 进程调度的时机、切换与过程、方式
知识总览
2.1.7.1 进程调度的时机
进程调度(低级调度),就是按照某种算法从就绪队列中选择一个进程为其分配处理机。
需要注意的是一些表述的问题。
进程在操作系统内核程序临界区中不能进行调度和切换。√
进程处于临界区不能进行处理机调度。×
这里两个表述的差异就在于名词:内核程序临界区
和临界区
的区别。
临界资源:一个时间段只允许一个进程使用的资源。各进程需要互斥地访问临界资源。
临界区:访问临界资源的那段代码。
内核程序临界区
一般是用来访问某种内核数据结构的,比如进程的就绪队列。这个时候一般来说快点访问完快点结束。这涉及到封锁表
的问题,在数据库中我们也曾经谈过这个上锁的问题,实际上操作系统也有上锁,也就是说,当你的进程1在访问内核程序的临界资源的时候,其他进程例如进程2无法同时访问,因为该内核程序临界资源被进程1上锁了,也就是说,此时如果你还去做进程的调度和切换,势必会导致占用该资源时间过长,拖延了其他进程使用该资源的时间;如果不是内核程序的临界资源倒也无所谓,但是如果是内核程序临界区访问的临界资源不尽快释放的话,极有可能影响到操作系统内核的其他管理工作。因此在访问内核程序临界区期间不能进行调度和切换。
而如果不是内核程序,是普通的临界区如打印机打印,那么在打印机打印完成之前,进程一直处于临界区内,临界资源不会解锁。但打印机又是慢速设备,CPU帮操作系统把进程对应的资源塞到打印机门口了,然后一直在等待打印完,这是不合理的,此时如果一直不允许进程调度的话就会导致CPU一直空闲。
普通临界区访问的临界资源不会直接影响操作系统内核的管理工作。因此在访问普通临界区时可以进行调度和切换。
回到前面讲的进程调度的时机。有的系统中,只允许进程主动放弃处理机;有的系统中,进程可以主动放弃处理机,当有更紧急的任务需要处理时,也会强行剥夺处理机(被动放弃)。由此我们引出了下一小节:进程调度的方式。
2.1.7.2 进程调度的方式
进程调度的方式可以分为两种:非剥夺调度方式
和剥夺调度方式
。
非剥夺调度方式,也称为
非抢占方式
。即只允许进程主动放弃处理机。在运行过程中即便有更紧迫的任务到达,当前进程依然会继续使用处理机,直到该进程终止或主动要求进入阻塞态。这种方式实现简单,系统开销小但是无法及时处理紧急任务,适合早期的批处理系统。
剥夺调度方式,又称为
抢占方式
。当一个进程正在处理机上执行时,如果有一个更重要或更紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给更重要紧迫的那个进程。这种方式可以优先处理更紧急的过程,也可以实现让各进程按时间片轮流执行的功能(通过时钟中断)。适合于分时操作系统、实时操作系统。
2.1.7.3 进程的切换和过程
这里需要知道的是两个每次的区别:狭义进程调度
和进程切换
的区别。
狭义的进程调度指的是从就绪队列中选中
一个要运行的进程。这个进程可以是刚刚被暂停执行的进程,也可能是另一个进程。
进程切换是指一个进程让出处理机,由另一个进程占用处理机的过程。
广义的进程调度包含了选择一个进程
和进程切换
两个步骤。
进程切换的过程主要完成了:
- 对原来运行进程各种数据的保存
- 对新的进程各种数据的恢复
如:程序计数器、程序状态字、各种数据寄存器等处理机现场信息,这些信息一般保存在进程控制块。
注意:进程切换是有代价的,因此如果过于频繁地进行进程调度、切换,比如会使整个系统的效率降低,使系统大部分时间都花在了进程切换上,而真正用于执行过程的时间减少。
2.1.7.4 小结
该小节含有的知识较多,不是考试的重点,但是也需要理解。
2.1.8 调度算法的评价指标
知识总览
需要注意的是,这一部分的知识要学会计算
2.1.8.1 CPU利用率
在早期,由于CPU造价极其昂贵,因此人们会希望让CPU尽可能多地工作。由此,引出了下面的概念。
CPU利用率:指CPU“忙碌”的时间占总时间的比例。,即\(利用率 = \frac{忙碌的时间}{总时间}\)。
在有的题目中,还会要求计算某种设备的利用率。
某计算机只支持单道程序,某个作业刚开始需要在CPU上运行5秒,再用打印机打印输出5秒,之后再执行5秒,才能结束。在此过程中,CPU利用率、打印机利用率分别是多少?
\(CPU利用率 = \frac{5+5}{5+5+5} = 66.66\)%
\(打印机利用率 = \frac{5}{15} = 33.33\)%
需要注意的是,考研中一般不会出这么简单的题目,而是会考查多道程序并发执行的情况,这时候可以利用
甘特图
来辅助计算。
2.1.8.2 系统吞吐量
对于计算机来说,人们总希望能用尽可能少的时间处理完尽可能多的作业。
系统吞吐量:单位时间内完成作业的数量。
系统吞吐量 = \(\frac{总共完成了多少道作业}{总共花了多少时间}\)
某计算机系统处理完10道作业,共花费了100秒,则系统吞吐量为?
10/100 = 0.1道/秒
2.1.8.3 周转时间
对于计算机的用户来说,他很关心自己的作业从提交到完成花了多少时间。这就是周转时间
。周转时间是指作业被提交给系统开始,到作业完成为止的这段时间间隔。
其包括四个部分:作业在外存后备队列上等待作业调度的时间、进程在就绪队列上等待进程调度的时间、进程在CPU上执行的时间、进程等待I/O操作完成的时间。后三项在一个作业的整个处理过程中,可能发生多次。
作业周转时间 = 作业完成时间-作业提交时间
对于单个用户来说,更关心自己的单个作业的周转情况
平均周转时间 = \(\frac{各作业周转时间之和}{作业数}\)
对于操作系统来说,更关心系统的整体表现,因此更关心所有作业周转时间的平均值。
有的作业运行时间短,有的作业运行时间长,因此在周转时间相同的情况下,运行时间不同的作业,给用户的感觉肯定是不一样的。
这么说的话,用户如何关心自己作业在周转时间的实际表现呢?这时候就引出了带权周转时间
。
带权周转时间 = \(\frac{作业周转时间}{作业实际运行的时间} = \frac {作业完成时间 - 作业提交时间}{作业实际运行的时间}\)
这样的话,对于周转时间相同的两个作业,实际运行时间长的作业在相同时间内被服务的时间更多,带权周转时间小,用户满意度更高。
而对于实际运行时间相同的两个作业,周转时间短的带权周转时间更小,用户满意度更高。
从公式来看,作业提交后不一定开始处理,所以分子肯定大于分母,也就是说,带权周转时间必然大于1,而且带权周转时间与周转时间都是越小越好。
平均带权周转时间 = \(\frac{各作业带权周转时间之和}{作业数}\)
相信上面的概念不好理解,我们下面用几个计算例子来理解:
设有三道作业,它们的提交时间和运行时间见下表:
作业号 提交时间/时 运行时间/h 1 10:00 2 2 10:10 1 3 10:25 0.25 注:为计算方便,“时”均为十进制。
试给出在下面两种调度算法下,作业的执行顺序、平均周转时间和带权周转时间。
- 先来先服务(FCFS)调度算法
- 短作业优先(SJF)调度算法
采用FCFS调度算法时,作业的执行顺序是作业1->作业2->作业3,根据题意可得下表:
作业号 提交时刻/时 运行时间/h 开始时刻/时 完成时刻/时 1 10:00 2 10:00 12:00 2 10:10 1 12:00 13:00 3 10:25 0.25 13:00 13:15 那么,由公式可得:
\(平均周转时间 =\frac{各作业周转时间之和}{作业数} = [(12-10)+(13-10:10)+(13:25-10:25)]/3 = 2.55h\)
\(平均带权周转时间 = \frac{各作业带权周转时间之和}{作业数} = [(12-10)/2+(13-10:10)/1+(13.15-10.25)/0.25]/3 = 5.05h\)
采用SJF调度算法时,作业的执行顺序是作业1->作业3->作业2,根据题意可得下表:
作业号 提交时刻/时 运行时间/h 开始时刻/时 完成时刻/ 1 10:00 2 10:00 12.00 2 10:10 1 12:15 13:15 3 10:25 0.25 12:00 12:15 那么,由公式可得:
\(平均周转时间 = [(12-10)+(13:15-10:10)+(12:15-10:25)]/3=[2+3.08+1.83]/3=2.3h\)
\(带权平均周转时间 = (2/2+3.08/1+1.83/0.25)/3=3.8h\)
2.1.8.4 等待时间
计算机的用户希望自己的作业尽可能少的等待处理机。
等待时间,指进程/作业
处于等待处理机状态时间之和
,等待时间越长,用户满意度越低。
对于进程来说,等待时间就是指进程建立后等待被服务的时间之和,在等待I/O完成的期间其实进程也是在被服务的,所以不计入等待时间。对于作业来说,不仅要考虑建立进程后的等待时间,还要加上作业在外存后备队列中等待的时间。
一个作业作业总共需要被CPU服务多久,被I/O设备服务多久一般是确定不变的,因此调度算法其实只会影响作业/进程的等待时间。当然,与前面指标类似,也有“平均等待时间”来评价整体性能。
2.1.8.5 响应时间
对于计算机用户来说,会希望自己提交的请求(比如通过键盘输入了一个调试指令)尽早地开始被系统服务、回应。由此引出了响应时间的概念:
响应时间
,指从用户提交请求
到首次产生响应
所用的时间。
2.1.8.6 小结
2.1.9 调度算法
知识总览
学习各种调度算法的思路
- 算法思想
- 算法规则
- 这种调度算法是用于作业调度还是进程调度?
- 抢占式或是非抢占式
- 优点和缺点
- 是否会导致
饥饿
(某进程/作业长期得不到服务)
2.1.9.1 先来先服务
知识点 | 说明 |
---|---|
英文名 | FCFS,即First Come First Serve |
算法思想 | 主要从公平的角度来考虑,类似于我们生活上排队买东西的例子 |
用于进程/作业调度 | 用于作业调度时,考虑的是哪个作业先到达后备队列;用于进程调度时,考虑的是哪个进程先到达就绪队列 |
是否可抢占? | 非抢占式算法 |
优缺点 | 优点:公平、算法实现简单;缺点:排在长作业后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好。 |
是否会导致饥饿 | 否 |
例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用先来先服务调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。
周转时间 = 完成时间-到达时间
P1 = 7-0 = 7 ; P2 = 11- 2 = 9 ; P3 = 12-4 = 8 ; P4 = 16-5 =11
带权周转时间 = 周转时间/运行时间
P1 = 7/7 = 1;P2 = 9/4 = 2.25 ; P3 = 8/1 = 8 ; P4 = 11/4 = 2.75
等待时间 = 周转时间-运行时间
P1 = 7-7 = 0 ;P2 = 9-4 = 5 ; P3 = 8-1 = 7 ; P4 = 11-4 = 7
这里需要注意的是,本例中的进程都是纯计算型的过程,一个进程到达后要么在等待,要么在运行。如果是又有计算、又有I/O操作的过程,其等待时间就是周转时间-运行时间-I/O操作的时间。
平均周转时间 = (7+9+8+11)/4 = 8.75
平均带权周转时间 = (1+2.25+8+2.75)/4 = 3.5
平均等待时间 = (0+5+7+7)/4 = 4.75
2.1.9.2 短作业优先
知识点 | 说明 |
---|---|
英文名 | SJF,即Shortest Job First |
算法思想 | 追求最少的平均等待时间,最少的平均周转时间、最少的平均带权周转时间。 |
用于进程/作业调度 | 既可用于作业调度,也可用于进程调度。用于进程调度时被称为“短作业优先(SPF)算法” |
是否可抢占? | SJF和SPF是非抢占式的算法。但是也有抢占式的版本——最短剩余时间优先算法(SRTN,Shortest Remaining Time Next) |
优缺点 | 优点:“最短的”平均等待时间、平均周转时间。缺点:不公平。对短作业有利,对长作业不利。可能产生饥饿现象。另外,作业/进程的运行时间是由用户提供的,并不一定真实,不一定能做到真正的短作业优先 |
是否会导致饥饿 | 会。如果源源不断地有短作业/进程到来,可能使长作业/进程长时间得不到服务,产生“饿死”现象。 |
例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用
非抢占式的短作业优先
调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。相比于FCFS算法,显然SPF算法的平均等待/周转/带权周转时间都要更低。
例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用
抢占式的短作业优先
调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。注:抢占式的短作业优先算法又称为
最短剩余时间优先算法(SRTN)
。相比于前两个算法,这个算法的指标更低。
经过上面的学习,我们可以知道一些知识。但是由于教材的不一,我们还有几个小细节需要注意:
- 如果题目中没有特别说明,所提到的“短作业/进程优先算法”默认是非抢占式的。
- 很多书上都会说“SJF调度算法的平均等待时间、平均周转时间最少”。严格来说这个表述的错误的,不严谨的。经过上面的学习我们可以知道最短剩余时间优先算法所得到的指标是最少的。如果仍然要用这里的表述,那我们可以加上前提条件:在所有进程都几乎同时到达时,采用SJF调度算法的平均等待时间、平均周转时间最少。
- 虽然根据上面的例子,SJF指标比FCFS低,但是实际上并不是最少,因为SRTN更少嘛。但是这个如果在选择题中,没有错误的选项,可以选择“SJF算法的平均等待时间、平均周转时间最少”这个选项。
2.1.9.3 对上述两种算法的思考
FCFS算法是在每次调度的时候选择一个等待时间最长的作业(进程)为其服务。但是没有考虑到作业的运行时间,因此导致了对短作业不友好的问题。
SJF算法是选择一个执行时间最短的作业为其服务。但是又完全不考虑各个作业的等待时间,因此导致了对长作业不友好的问题,甚至会造成饥饿问题。
那么有没有一个算法,即考虑到各个作业的等待时间,又能兼顾运行时间呢?这就要引出来我们下面的算法了。
2.1.9.4 高响应比优先
知识点 | 说明 |
---|---|
英文名 | HRRN,Highest Response Ratio Next |
算法思想 | 在每次调度时先计算各个作业/进程的响应比,选择响应比最高的作业/进程为其服务。其中响应比的计算公式为\(响应比 = \frac{等待时间+要求服务时间}{要求服务时间}\) |
用于进程/作业调度 | 既可用于作业调度,也可用于进程调度 |
是否可抢占? | 非抢占式的算法。因此只有当前运行的作业/进程主动放弃处理机时,才需要调度,才需要计算响应比。 |
优缺点 | 综合考虑了等待时间和运行时间(要求服务时间) |
是否会导致饥饿 | 不会 |
例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用
高响应比优先
调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。
2.1.9.5 小结
这几种算法主要关心对用户的公平性、平均周转时间、平均等待时间等评价系统整体性能的指标,但是不关心“响应时间”,也并不区分任务的紧急程度,因此对于用户来说,交互性很糟糕。因此这三种算法一般适合用于早期的批处理系统
,当然,FCFS算法也常结合其他的算法使用,在现在也扮演着很重要的角色。
在下一部分,我们会讲讲交互式系统
的调度算法。
2.2.0 交互式系统调度算法
2.3.1 进程同步和进程互斥
知识总览
2.3.1.1 什么是进程同步?
在前面,我们说过进程具有异步性
的特征。
而我们想让进程执行的顺序是可预知的,就需要进程同步机制。
曾经在2.1.4.3 管道通信我们说过,读进程和写进程并发地运行,当时我们说过,如果没写满,就不允许读;如果没读空,就不允许写。也就是说是一个先写后读
的顺序,而这当中又含有异步性
,我们不可控,这就需要进程同步
来帮我们解决了。
同步
亦称直接制约关系
,它是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而产生制约关系。进程间的直接制约关系就是源于它们之间的相互合作。
2.3.1.2 什么是进程互斥
进程的“并发”需要“共享”的支持。各个并发执行的进程不可避免的需要共享一些系统资源(比如内存,又如打印机、摄像头这样的I/O设备)。我们把资源共享方式分为两种:互斥共享方式
和同时共享方式
。
之前在2.1.7.1之中我们曾经讲过临界资源的概念。许多物理设备(比如摄像头、打印机)都属于临界资源。此外还有许多变量、数据、内存缓冲区等都属于临界资源。
对临界资源的访问,必须互斥
地进行。互斥,也叫做间接制约关系
。进程互斥
指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。当前访问临界资源的进程访问结束。释放该资源之后,另一个进程才能去访问临界资源。
对临界资源的互斥访问,可以在逻辑上分为四个部分:
do{
entry section;//进入区
critical section;//临界区
exit section;//退出区
remainder section;//剩余区
}
其中进入区
负责检查是否可进入临界区,若可进入,则应设置正在访问临界资源的标志(可以理解为数据库我们学过的上锁),以阻止其他进程同时进入临界区。临界区
就是访问临界资源的那段代码,退出区
负责解除正在访问临界资源的标志(可以理解为“解锁”),剩余区
做其他处理。
需要注意的是,临界区有时也叫做临界段
。
为了实现对临界资源的互斥访问,同时保证系统整体性能,需要遵循以下原则:
- 空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程立即进入。
- 忙则等待。当已有进程进入临界区时,其他试图进入临界区的进程必须等待。
- 有限等待。对于请求访问的进程,应该保证能在有限的时间内进入临界区,这实际上也是我们后面讲的活锁。
- 让权等待。当进程不能进入临界区时,应该立即释放处理机,防止进程忙等待,这实际上是为了防止死锁。