主要是按照王道考研408的ppt进行复习。
操作系统(Operating System, OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配;以提供给用户和其他软件方便的接口和环境;它是计算机系统中最基本的系统软件。
操作系统的四大特征:并发、共享、虚拟、异步。
一个分布式系统是若干个独立的计算机的集合, 但是对该系统的用户来说, 感觉该系统就像一台计算机一样。
网络操作系统:是伴随着计算机网络的发展而诞生的,能把网络中各个计算机有机地结合起来,实现数据传送等功能,实现网络中各种资源的共享(如文件共享)和各台计算机之间的通信。(如:WindowsNT就是一种典型的网络操作系统,网站服务器就可以使用)
分布式操作系统:主要特点是分布性和并行性。系统中的各台计算机地位相同,任何工作都可以分布在这些计算机上,由它们并行、协同完成这个任务。
个人计算机操作系统:如WindowsXP、MacOS,方便个人使用。
我们普通程序员写的程序就是“应用程序” 如加法指令、减法指令
微软、苹果有一帮人负责实现操作系统,他们写的就是“内核程序” 如内存清零指令
CPU有两种状态,“内核态”和“用户态”
处于内核态时,说明此时正在运行的是内核程序,此时可以执行特权指令
处于用户态时,说明此时正在运行的是应用程序,此时只能执行非特权指令
①刚开机时,CPU为“内核态”,操作系统内核程序先上CPU运行
②开机完成后,用户可以启动某个应用程序
③操作系统内核程序在合适的时候主动让出CPU,让该应用程序上CPU运行
④应用程序运行在“用户态”
⑤此时,一位猥琐黑客在应用程序中植入了一条特权指令,企图破坏系统…
⑥CPU发现接下来要执行的这条指令是特权指令,但是自己又处于“用户态”
⑦这个非法事件会引发一个中断信号
⑧“中断”使操作系统再次夺回CPU的控制权
⑨操作系统会对引发中断的事件进行处理,处理完了再把CPU使用权交给别的应用程序
切换:
内核态→用户态:执行一条特权指令——修改PSW的标志位为“用户态”,这个动作意味着操作系统将主动让出CPU使用权
用户态→内核态:由“中断”引发,硬件自动完成变态过程,触发中断信号意味着操作系统将强行夺回CPU的使用权
CPU上会运行两种程序,一种是操作系统内核程序,一种是应用程序
在合适的情况下,操作系统内核会把CPU的使用权主动让给应用程序(第二章进程管理相关内容)
“中断”是让操作系统内核夺回CPU使用权的唯一途径
“系统调用”是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以通过系统调用来请求获得操作系统内核的服务
文件操作系统调用:
进程管理系统调用:
网络通信系统调用:
内存管理系统调用:
信号处理系统调用:
管道和IPC系统调用:
时间和定时器系统调用:
进程由PCB、程序段、数据段组成,PCB是进程存在的唯一标志!
进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
语是一种特殊的程序,它的执行具有原子性。也就是说,这段程序的运行必须一气呵成,不可中断
进程控制会导致进程状态的转换。无论哪个进程控制原语,要做的无非三类事情:
1.更新PCB中的信息
a.所有的进程控制原语一定都会修改进程状态标志
b.剥夺当前运行进程的CPU使用权必然需要保存其运行环境
c.某进程开始运行前必然要恢复期运行环境
2.将PCB插入合适的队列
3.分配/回收资源
可以把线程理解为“轻量级进程”。
线程是一个基本的CPU执行单元,也是程序执行流的最小单位。引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务(如QQ视频、文字聊天、传文件)引入线程后,进程只作为除CPU之外的系统资源的分配单元(如打印机、内存地址空间等都是分配给进程的)。线程则作为处理机的分配单元。
线程有两种实现方式,早期实现的方式是用户级线程,后来实现的方式为内核级线程。
根据用户级线程和内核级线程的对应关系,可以把多线程模型分为一对一模型、一对多模型、多对一模型
临界资源:一个时间段内只允许一个进程使用的资源。各进程需要互斥地访问临界资源。
临界区:访问临界资源的那段代码。
内核程序临界区一般是用来访问某种内核数据结构的,比如进程的就绪队列(由各就绪进程的PCB组成)
当要求判断算法是否有利于cpu繁忙进程、io繁忙进程市,记住:cpu繁忙型进程接近于长进程,io繁忙型进程接近短进程。
下表是先来先服务、短进程优先、高响应比优先算法的优缺点。其中响应比 = (等待时间 + 服务时间) / 服务时间
优先级调度算法
根据优先级是否可以动态改变,可将优先级分为静态优先级和动态优先级两种。
静态优先级:创建进程时确定,之后一直不变。
动态优先级:创建进程时有一个初始值,之后会根据情况动态地调整优先级。
操作系统更偏好 I/O型进程(或称 I/O繁忙型进程),如果优先让I/O繁忙型进程优先运行的话,则越有可能让I/O设备尽早地投入工作,则资源利用率、系统吞吐量都会得到提升。可以从追求公平、提升资源利用率等角度考虑:
如果某进程在就绪队列中等待了很长时间,则可以适当提升其优先级
如果某进程占用处理机运行了很长时间,则可适当降低其优先级
如果发现一个进程频繁地进行I/O操作,则可适当提升其优先级
多级反馈队列调度算法 是对其他调度算法的折中权衡
对逻辑资源的互斥访问代码,在逻辑上可以分为四个部分:进入区、临界区、退出区、剩余区。先加锁,然后访问临界资源,然后去掉锁,最后进行业务处理。
使用软件实现进程互斥,细节暂时不学习:
使用硬件实现进程互斥,细节暂时不学习:
进程互斥的四种软件实现方式(单标志法、双标志先检查、双标志后检查、Peterson算法)、进程互斥的三种硬件实现方式(中断屏蔽方法、TS/TSL指令、Swap/XCHG指令)存在着很严重的问题:
用户进程可以通过使用操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。
原语是一种特殊的程序段,其执行只能一气呵成,不可被中断。原语是由关中断/开中断指令实现的。
生产者消费者问题解决方案:
mutex是控制缓存区的互斥访问,对于所有的临界资源都要设置mutex互斥信号量
注意互斥mutex的P操作一定要在empty和full的P操作后面,否则可能会引起死锁。
吃苹果问题:
桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。
因为盘子最多只能装下一个水果,所以即便没有互斥信号量,四人对盘子的访问也一定是互斥的,所以这里可以去掉mutex。
还有读者写者问题,哲学家就餐问题,都不是知识性的问题,而是思维性的问题,这里暂时不记录。
管程是一种特殊的软件模块,有这些部分组成:
管程的基本特征:
破坏互斥条件:把只能互斥使用的资源改造为允许共享使用。
但并不是所有的资源都可以改造成可共享使用的资源。并且为了系统安全,很多地方还必须保护这种互斥性。因此,很多时候都无法破坏互斥条件。
破坏不剥夺条件:操作系统帮助进程剥夺资源。
实现起来比较复杂,反复地申请和释放资源会增加系统开销,降低系统吞吐量,释放已获得的资源可能造成前一阶段工作的失效,这种方法一般只适用于易保存和恢复状态的资源,如CPU。
破坏请求和保持条件:可以采用静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不让它投入运行。一旦投入运行后,这些资源就一直归它所有,该进程就不会再请求别的任何资源了。
有些资源可能只需要用很短的时间,因此如果进程的整个运行期间都一直保持着所有资源,就会造成严重的资源浪费,资源利用率极低。另外,该策略也有可能导致某些进程饥饿。
破坏循环等待条件:存在一种进程资源的循环等待链,链中的每一个进程已获得的资源同时被下一个进程所请求。可采用顺序资源分配法。首先给系统中的资源编号,规定每个进程必须按编号递增的顺序请求资源,同类资源(即编号相同的资源)一次申请完。
不方便增加新的设备,因为可能需要重新分配所有的编号;进程实际使用资源的顺序可能和编号递增顺序不一致,会导致资源浪费;必须按规定次序申请资源,用户编程麻烦。
所谓安全序列,就是指如果系统按照这种序列分配资源,则每个进程都能顺利完成。只要能找出一个安全序列,系统就是安全状态。
如果系统处于安全状态,就一定不会发生死锁。如果系统进入不安全状态,就可能发生死锁(处于不安全状态未必就是发生了死锁,但发生死锁时一定是在不安全状态)
银行家算法核心思想:在进程提出资源申请时,先预判此次分配是否会导致系统进入不安全状态。如果会进入不安全状态,就暂时不答应这次请求,让该进程先阻塞等待。
解除死锁的主要方法有:
连续内存分配,指一个进程的数据连续地存放在内存中
在单一连续分配方式中,内存被分为系统区和用户区。系统区通常位于内存的低地址部分,用于存放操作系统相关数据;用户区用于存放用户进程相关数据。内存中只能有一道用户程序,用户程序独占整个用户区空间。
优点:实现简单;无外部碎片;可以采用覆盖技术扩充内存;不一定需要采取内存保护(eg:早期的 PC 操作系统 MS-DOS)。
缺点:只能用于单用户、单任务的操作系统中;有内部碎片;存储器利用率极低。
在固定分区分配中,将整个用户空间划分为若干个固定大小的分区,在每个分区中只装入一道作业,这样就形成了最早的、最简单的一种可运行多道程序的内存管理方式。分区大小可以采取相等或不相等。
操作系统需要建立一个数据结构——分区说明表,来实现各个分区的分配与回收。每个表项对应一个分区,通常按分区大小排列。每个表项包括对应分区的大小、起始地址、状态(是否已分配)。
优点:实现简单,无外部碎片。
缺点:a. 当用户程序太大时,可能所有的分区都不能满足需求,此时不得不采用覆盖技术来解决,但这又会降低性能;b. 会产生内部碎片,内存利用率低。
动态分区分配又称为可变分区分配。这种分配方式不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。因此系统分区的大小和数目是可变的。
首次适应算法
算法思想:每次都从低地址开始查找,找到第一个能满足大小的空闲分区。
如何实现:空闲分区以地址递增的次序排列。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
邻近适应算法
算法思想:首次适应算法每次都从链头开始查找的。这可能会导致低地址部分出现很多小的空闲分区,而每次分配查找时,都要经过这些分区,因此也增加了查找的开销。如果每次都从上次查找结束的位置开始检索,就能解决上述问题。
如何实现:空闲分区以地址递增的顺序排列(可排成一个循环链表)。每次分配内存时从上次查找结束的位置开始查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
最坏适应算法 又称 最大适应算法(Largest Fit)
算法思想:为了解决最佳适应算法的问题——即留下太多难以利用的小碎片,可以在每次分配时优先使用最大的连续空闲区,这样分配后剩余的空闲区就不会太小,更方便使用。
如何实现:空闲分区按容量递减次序链接。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区
最佳适应算法
算法思想:由于动态分区分配是一种连续分配方式,为各进程分配的空间必须是连续的一整片区域。因此为了保证当“大进程”到来时能有连续的大片空间,可以尽可能多地留下大片的空闲区,即,优先使用更小的空闲区。
如何实现:空闲分区按容量递增次序链接。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
将内存空间分为一个个大小相等的分区(比如:每个分区4KB),每个分区就是一个**“页框”(页框=页帧=内存块=物理块=物理页面)。每个页框有一个编号,即“页框号”(页框号=页帧号=内存块号=物理块号=物理页号),页框号从0开始。
将进程的逻辑地址**空间也分为与页框大小相等的一个个部分,每个部分称为一个“页”或“页面” 。每个页面也有一个编号,即“页号”,页号也是从0开始。
操作系统以页框为单位为各个进程分配内存空间。进程的每个页面分别放入一个页框中。也就是说,进程的页面与内存的页框有一一对应的关系。
各个页面不必连续存放,可以放到不相邻的各个页框中。(注:进程的最后一个页面可能没有一个页框那么大。也就是说,分页存储有可能产生内部碎片,因此页框不能太大,否则可能产生过大的内部碎片造成浪费)
为了能知道进程的每个页面在内存中存放的位置,操作系统要为每个进程建立一张页表。注:页表通常存在PCB(进程控制块)中。
逻辑地址到物理地址的转换
如果要访问逻辑地址 A,则
①确定逻辑地址A 对应的“页号”P
②找到P号页面在内存中的起始地址(需要查页表)
③确定逻辑地址A 的“页内偏移量”W
逻辑地址A 对应的物理地址 = P号页面在内存中的起始地址+页内偏移量W
如何确定一个逻辑地址对应的页号、页内偏移量?
页号 = 逻辑地址 / 页面长度 (取除法的整数部分)
页内偏移量 = 逻辑地址 % 页面长度(取除法的余数部分)
页面大小往往是2的k次幂。
如果每个页面大小为 2KB,用二进制数表示逻辑地址,则低 K 位即为页内偏移量,其余部分就是页号。因此,如果让每个页面的大小为 2 的整数幂,计算机硬件就可以很方便地得出一个逻辑地址对应的页号和页内偏移量,而无需进行除法运算,从而提升了运行速度。
基本地址变换机构(单级页表)如下图所示,使用快表和不使用快表的对比后如下表所示。
单级页表的问题:因为页表项是连续存储的,像数组一样,所以我们需要把所有的页表项都放在内存中。根据局部性原理可知,很多时候,进程在一段时间内只需要访问某几个页面就可以正常运行了。因此没有必要让整个页表都常驻内存。
所以引入二级页表,把页表再分页并离散存储,然后再建立一张页表记录页表各个部分的存放位置,称为页目录表,或称外层页表,或称顶层页表。可以在需要访问页面时才把页面调入内存(虚拟存储技术)。可以在页表项中增加一个标志位,用于表示该页面是否已经调入内存
二级页表地址转换过程:
①按照地址结构将逻辑地址拆分成三部分
②从PCB 中读出页目录表始址,再根据一级页号查页目录表,找到下一级页表在内存中的存放位置
③根据二级页号查二级页表,找到最终想访问的内存块号
④结合页内偏移量得到物理地址
分段和分页很类似,有段号、段表的类似概念。
页是信息的物理单位。分页的主要目的是为了实现离散分配,提高内存利用率。分页仅仅是系统管理上的需要,完全是系统行为,对用户是不可见的。
段是信息的逻辑单位。分段的主要目的是更好地满足用户需求。一个段通常包含着一组属于一个逻辑模块的信息。分段对用户是可见的,用户编程时需要显式地给出段名。
页的大小固定且由系统决定。段的长度却不固定,决定于用户编写的程序。
分页的用户进程地址空间是一维的,程序员只需给出一个记忆符即可表示一个地址。
分段的用户进程地址空间是二维的,程序员在标识一个地址时,既要给出段名,也要给出段内地址。
分段比分页更容易实现信息的共享和保护。因为进程数据的长度往往是不固定的,所以使用页表很难实现访问权限控制,但使用段表的话,可以把一个进程的所有数据装入一个段中,这样就比较容易实现权限控制。
请求分页存储管理与基本分页存储管理的主要区别:
在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序。
若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存。
在请求分页系统中,每当要访问的页面不在内存时,便产生一个缺页中断,然后由操作系统的缺页中断处理程序处理中断。
此时缺页的进程阻塞,放入阻塞队列,调页完成后再将其唤醒,放回就绪队列。如果内存中有空闲块,则为进程分配一个空闲块,将所缺页面装入该块,并修改页表中相应的页表项。
如果内存中没有空闲块,则由页面置换算法选择一个页面淘汰,若该页面在内存期间被修改过,则要将其写回外存。未修改过的页面不用写回外存。
缺页中断是因为当前执行的指令想要访问的目标页面未调入内存而产生的,因此属于内中断一条指令在执行期间,可能产生多次缺页中断。
最佳置换算法(OPT,Optimal):每次选择淘汰的页面将是以后永不使用,或者在最长时间内不再被访问的页面,这样可以保证最低的缺页率。
最佳置换算法可以保证最低的缺页率,但实际上,只有在进程执行的过程中才能知道接下来会访问到的是哪个页面。操作系统无法ᨀ前预判页面访问序列。因此,最佳置换算法是无法实现的。
先进先出置换算法(FIFO):每次选择淘汰的页面是最早进入内存的页面
最近最久未使用置换算法(LRU,least recently used):每次淘汰的页面是最近最久未使用的页面实现方法:赋予每个页面对应的页表项中,用访问字段记录该页面自上次被访问以来所经历的时间t。当需要淘汰一个页面时,选择现有页面中 t 值最大的,即最近最久未使用的页面。
时钟置换算法是一种性能和开销较均衡的算法,又称CLOCK算法,或最近未用算法(NRU,NotRecently Used)
简单的CLOCK 算法实现方法:为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列。当某页被访问时,其访问位置为1。当需要淘汰一个页面时,只需检查页的访问位。如果是0,就选择该页换出;如果是1,则将它置为0,暂不换出,继续检查下一个页面,若第一轮扫᧿中所有页面都是1,则将这些页面的访问位依次置为0后,再进行第二轮扫描(第二轮扫描中一定会有访问位为0的页面,因此简单的CLOCK 算法选择一个淘汰页面最多会经过两轮扫描)
文件的逻辑结构可分为有结构文件和无结构文件,有结构文件如下图所示可以细分为三类,无结构文件指二进制流文件,无明显结构,比如txt
多个用户共享同一个文件,意味着系统中只有“一份”文件数据。并且只要某个用户修改了该文件的数据,其他用户也可以看到文件数据的变化。而不是说多个用户每个人把文件复制了一份。
索引结点,是一种文件目录瘦身策略。由于检索文件时只需用到文件名,因此可以将除了文件名之外的其他信息放到索引结点中。这样目录项就只需要包含文件名、索引结点指针。
一次磁盘读/写操作需要的时间:
先来先服务算法(FCFS)根据进程请求访问磁盘的先后顺序进行调度。
最短寻找时间优先(SSTF)SSTF 算法会优先处理的磁道是与当前磁头最近的磁道。可以保证每次的寻道时间最短,但是并不能保证总的寻道时间最短。(其实就是贪心算法的思想,只是选择眼前最优,但是总体未必最优)
扫描算法(SCAN)在SSTF的基础上,为了防止饥饿问题,规定只有磁头移动到最外侧磁道的时候才能往内移动,移动到最内侧磁道的时候才能往外移动。这就是扫描算法(SCAN)的思想。由于磁头移动的方式很像电梯,因此也叫电梯算法。
循环扫描算法(C-SCAN)在SCAN算法的基础上,规定只有磁头朝某个特定方向移动时才处理磁道访问请求,而返回时直接快速移动至起始端而不处理任何请求。
LOOK 调度算法在SCAN的基础上规定,如果在磁头移动方向上已经没有别的请求,就可以立即改变磁头移动方向。
C-LOOK 调度算法在C-SCAN基础上规定,如果磁头移动的方向上已经没有磁道访问请求了,就可以立即让磁头返回,并且磁头只需要返回到有磁道访问请求的位置即可
CPU无法直接控制I/O设备的机械部件,因此I/O设备还要有一个电子部件作为CPU和I/O设备机械部件之间的“中介”,用于实现CPU对设备的控制。
这个电子部件就是I/O控制器,又称设备控制器。CPU可控制I/O控制器,又由I/O控制器来控制设备的机械部件
设备独立性,也称为设备无关性,设备独立性软件:负责实现与设备驱动器的统一接口、设备命名、设备的保护以及设备的分配与释放等,同时为设备管理和数据传送提供必要的存储空间。
引入脱机技术后,缓解了CPU与慢速I/O设备的速度矛盾。另一方面,即使CPU在忙碌,也可以提前将数据输入到磁带;即使慢速的输出设备正在忙碌,也可以提前将数据输出到磁带。
在外围控制机的控制下,慢速输入设备的数据先被输入到更快速的磁带上。之后主机可以从快速的磁带上读入数据,从而缓解了速度矛盾
“假脱机技术”,又称“SPOOLing 技术”是用软件的方式模拟脱机技术。 SPOOLing 系统的组成如下:
要实现SPOOLing 技术,必须要有多道程序技术的支持。系统会建立 “输入进程”和 “输出进程”。
在输入进程的控制下,“输入缓冲区”用于暂存从输入设备输入的数据,之后再转存到输入井中。
在输出进程的控制下,“输出缓冲区”用于暂存从输出井送来的数据,之后再传送到输出设备上
独占式设备——只允许各个进程串行使用的设备。一段时间内只能满足一个进程的请求。
共享设备——允许多个进程“同时”使用的设备(宏观上同时使用,微观上可能是交替使用)。可以同时满足多个进程的使用请求。
打印机是种“独占式设备”,但是可以用SPOOLing 技术改造成“共享设备”。
当多个用户进程提出输出打印的请求时,系统会答应它们的请求,但是并不是真正把打印机分配给他们,而是由假脱机管理进程为每个进程做两件事:
(1)在磁盘输出井中为进程申请一个空闲缓冲区(也就是说,这个缓冲区是在磁盘上的),并将要打印的数据送入其中;
(2)为用户进程申请一张空白的打印请求表,并将用户的打印请求填入表中(其实就是用来说明用户的打印数据存放位置等信息的),再将该表挂到假脱机文件队列上。当打印机空闲时,输出进程会从文件队列的队头取出一张打印请求表,并根据表中的要求将要打印的数据从输出井传送到输出缓冲区,再输出到打印机进行打印。用这种方式可依次处理完全部的打印任务
设备的固有属性可分为三种:独占设备、共享设备、虚拟设备。
独占设备——一个时段只能分配给一个进程(如打印机)
共享设备——可同时分配给多个进程使用(如磁盘),各进程往往是宏观上同时共享使用设备,而微观上交替使用。
虚拟设备——采用 SPOOLing 技术将独占设备改造成虚拟的共享设备,可同时分配给多个进程使用(如采用 SPOOLing 技术实现的共享打印机)
安全分配方式:为进程分配一个设备后就将进程阻塞,本次I/O完成后才将进程唤醒。
不安全分配方式:进程发出I/O请求后,系统为其分配I/O设备,进程可继续执行,之后还可以发出新的I/O请求。只有某个I/O请求得不到满足时才将进程阻塞。
缓冲区是一个存储区域,可以由专门的硬件寄存器组成,也可利用内存作为缓冲区。
假设某用户进程请求某种块设备读入若干块的数据。若采用单缓冲的策略,操作系统会在主存中为其分配一个缓冲区(若题目中没有特别说明,一个缓冲区的大小就是一个块)。
注意:当缓冲区数据非空时,不能往缓冲区冲入数据,只能从缓冲区把数据传出;当缓冲区为空时,可以往缓冲区冲入数据,但必须把缓冲区充满以后,才能从缓冲区把数据传出。
假设某用户进程请求某种块设备读入若干块的数据。若采用双缓冲的策略,操作系统会在主存中为其分配两个缓冲区(若题目中没有特别说明,一个缓冲区的大小就是一个块)
缓冲池由系统中共用的缓冲区组成。这些缓冲区按使用状况可以分为:空缓冲队列、装满输入数据的缓冲队列(输入队列)、装满输出数据的缓冲队列(输出队列)