文章目录
什么是操作系统
操作系统是管理和控制计算机硬件与软件资源的计算机程序。
操作系统主要有五大功能:处理机管理(CPU)、进程管理、内存管理、设备管理和文件系统管理。
系统调度(分进程和线程)
引起进程调度的原因有以下几类:
(1)正在执行的进程执行完毕。
(2)执行中的进程自己调用阻塞原语将自己阻塞起来进入睡眠状态。
(3)执行中的进程调用了 P 原语操作,从而因资源不足而阻塞;或调用 V 原语操作激活了等待资源的进程队列。
(4)在分时系统中,当一进程用完一个时间片。
(5)就绪队列中某进程的优先级变得高于当前执行进程的优先级,也将引起进程调度。
进程的上下文切换
将CPU硬件状态从一个进程换到另一个进程的过程称为上下文切换,其实就是运行环境的切换。
进程运行时,其硬件状态保存在CPU上的寄存器中。寄存器有:程序计数器、程序状态寄存器、栈指针、通用寄存器、其他控制寄存器的值
进程不运行时,这些寄存器的值保存在进程控制块中;当操作系统要运行一个新的进程时,将进程控制块中相关值送到对应的寄存器中。
进程的内存布局:代码块、数据区、堆、栈段 寄存器等等。
(1)就绪状态。当进程已分配了除 CPU 以外的所有必要的资源后,只要能再获得处理机,便能立即执行,把这时的进程状态称为就绪状态。在一个系统中,可以有多个进程同时处于就绪状态,通常把它们排成一个队列,称为就绪队列。
(2)执行状态指进程已获得处理机,其程序正在执行。在单处理机系统中,只能有一个进程处于执行状态。
(3)阻塞状态指进程因发生某事件(如请求 I/O、申请缓冲空间等)而暂停执行时的状态,亦即进程的执行受到阻塞,故称这种暂停状态为阻塞状态,有时也称为“等待”状态,或“睡眠”状态。通常将处于阻塞状态的进程排成一个队列,称为阻塞队列。
在某些操作系统中存在挂起状态
一般情况下,系统按照以下流程创建一个进程:
1.分配、初始化 PCB
2.初始化机器寄存器
3.拷贝、初始化内存页表
4.从硬盘加载程序代码到内存
5.将进程加入就绪队列
6. 进程调度时,选择该进程并切换到用户态开始执行进程
系统通过快速切换进程,让每一个进程都有一定的时间片来响应用户提交的请求;在用户的视角,好像每个进程都在同时执行一样。系统切换进程的方法叫做进程调度算法,基本的调度算法有:
(1)先来先服务(FCFS)
算法简单,但效率低;对长作业比较有利,但对短作业不利(相对SJF和高响应比);有利于CPU繁忙型作业,而不利于I/O繁忙型作业。
(2)时间片轮转
时间片轮转调度算法主要适用于分时系统。系统将所有就绪进程按到达时间的先后次序排成一个队列,进程调度程序总是选择就绪队列中第一个进程执行,即先来先服务的原则,但仅能运行一个时间片,如100ms。在使用完一个时间片后,即使进程并未完成其运行,它也必须释放出(被剥夺)处理机给下一个就绪的进程,而被剥夺的进程返回到就绪队列的末尾重新排队,等候再次运行。
在时间片轮转调度算法中,时间片的大小对系统性能的影响很大。如果时间片足够大,以至于所有进程都能在一个时间片内执行完毕,则时间片轮转调度算法就退化为先来先服务调度算法。如果时间片很小,那么处理机将在进程间过于频繁切换,使处理机的开销增大,而真正用于运行用户进程的时间将减少。因此时间片的大小应选择适当。
(3)短作业优先(shortest job first)平均等待时间、平均周转时间最少
该算法对长作业不利。更严重的是,如果有一长作业进入系统的后备队列,由于调度程序总是优先调度那些 (即使是后进来的)短作业,将导致长作业长期不被调度
该算法完全未考虑作业的紧迫程度,因而不能保证紧迫性作业会被及时处理。
由于作业的长短只是根据用户所提供的估计执行时间而定的,而用户又可能会有意或无意地缩短其作业的估计运行时间,致使该算法不一定能真正做到短作业优先调度。
(4)优先级调度
非剥夺式优先级调度算法。当某一个进程正在处理机上运行时,即使有某个更为重要或紧迫的进程进入就绪队列,仍然让正在运行的进程继续运行,直到由于其自身的原因而主动让出处理机时(任务完成或等待事件),才把处理机分配给更为重要或紧迫的进程。
剥夺式优先级调度算法。当一个进程正在处理机上运行时,若有某个更为重要或紧迫的进程进入就绪队列,则立即暂停正在运行的进程,将处理机分配给更重要或紧迫的进程。
(5)多级反馈队列调度(优先级+时间片轮转)
算法的实现思想:
应设置多个就绪队列,并为各个队列赋予不同的优先级,第1级队列的优先级最高,第2级队列次之,其余队列的优先级逐次降低。
赋予各个队列中进程执行时间片的大小也各不相同,在优先级越高的队列中,每个进程的运行时间片就越小。例如,第2级队列的时间片要比第1级队列的时间片长一倍, ……第i+1级队列的时间片要比第i级队列的时间片长一倍。
当一个新进程进入内存后,首先将它放入第1级队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第2级队列的末尾,再同样地按FCFS 原则等待调度执行;如果它在第2级队列中运行一个时间片后仍未完成,再以同样的方法放入第3级队列……如此下去,当一个长进程从第1级队列依次降到第 n 级队列后,在第 n 级队列中便釆用时间片轮转的方式运行。
** 仅当第1级队列为空时,调度程序才调度第2级队列中的进程运行 ** ;仅当第1 ~ (i-1)级队列均为空时,才会调度第i级队列中的进程运行。如果处理机正在执行第i级队列中的某进程时,又有新进程进入优先级较高的队列(第 1 ~ (i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由 ** 调度程序把正在运行的进程放回到第i级队列的末尾,把处理机分配给新到的更高优先级的进程。**
多级反馈队列的优势有:
终端型作业用户:短作业优先。
短批处理作业用户:周转时间较短。
长批处理作业用户:经过前面几个队列得到部分执行,不会长期得不到处理。
进程通信
管道
共享内存
共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
特点:
共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
因为多个进程可以同时操作,所以需要进行同步。
信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
信号量
信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
一般 P 操作与 V 操作的定义如下所述。利用 P、V 原语(因为都是不可分割的原子操作,所以叫原语)和信号量可以方便地解决并发进程对临界区的进程互斥问题。
P 操作:
P(sem){
sem = sem - 1;
if(sem < 0)进程进入等待状态;
else 继续进行;} V 操作:
V(sem){
sem = sem + 1;
if(sem ≤ 0)唤醒队列中的一个等待进程;
else 继续进行;}
特点:
1.信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
2.信号量基于操作系统的 P、V 操作,程序对信号量的操作都是原子操作。
3.每次对信号量的 P、V 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
4.支持信号量组。
消息队列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
特点:
消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
socket
更为一般的进程间通信机制,可用于不同机器之间的进程间通信。
死锁
- 概念
两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 - 死锁产生的原因
(1)因竞争资源发生死锁
现象:系统中供多个进程共享的资源的数目不足以满足全部进程的需要时,就会引起对诸资源的竞争而发生死锁现象
(2)进程推进顺序不当发生死锁 - 死锁产生的四个必要条件(有一个条件不成立,则不会产生死锁)
(1)互斥条件:一个资源一次只能被一个进程使用
(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
(3)不剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
(4)循环等待条件:若干进程之间形成一种头尾相接的环形等待资源关系 - 处理死锁的方法
只要上述一个条件不成立,就不会产生死锁,所以解决死锁的基本方法有:预防死锁、避免死锁、检测死锁、解除死锁。
(1)预防死锁(破坏四个必要条件):
资源一次性分配:(破坏请求和保持条件)
可剥夺资源:即当某进程新的资源未满足时,释放已占有的资源(破坏不可剥夺条件)
资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)
(2)避免死锁(银行家算法):
预防死锁的几种策略,会严重地损害系统性能。因此在避免死锁时,要施加较弱的限制,从而获得较满意的系统性能。由于在避免死锁的策略中,允许进程动态地申请资源。因而,系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,进程等待。其中最具有代表性的避免死锁算法是银行家算法。
(3)检测死锁
通过将资源分配图简化的方法来检测系统状态S是否为死锁状态。
(4)解除死锁
当发现有进程死锁后,便应立即把它从死锁状态中解脱出来,常采用的方法有:
①剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态。
②撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用,死锁状态消除为止。
内存管理
什么是内存
内存是用来存放数据的硬件。程序执行前都是先放在内存中才能被CPU执行
相对地址 绝对地址 逻辑地址 物理地址 线性地址
逻辑地址 是指由程序产生的与段相关的偏移地址部分,它是相对于当前进程数据段的地址
线性地址(Linear Address)是逻辑地址到物理地址转换的中间层。程序代码经编译后会产生逻辑地址,或者说是段中的偏移地址,加上相应段的基地址就生成了一个线性地址。 若启用了分页机制,则线性地址会再此转换产生一个物理地址。若没有启用分页机制,则线性地址就是物理地址。
物理地址(Physical Address)是指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终地址。若启用了分页机制,则线性地址会使用页目录和页表中的项转换为物理地址。若没有启用分页机制,则线性地址直接就是物理地址。
相对地址又称逻辑地址,绝对地址又称物理地址。
为什么要内存管理 虚拟内存
1.为什么要进行内存管理?
(1).为什么要进行内存管理:因为内存是稀缺资源,容量很少,早期内存管理地址空间不隔离,一个进程占据全部内存空间,程序并发性小,造成内存使用效率低下;引入虚拟内存技术,现在的内存管理不是对物理地址的管理,而是对虚拟地址的管理;
(2).如何管理虚拟内存空间:通过MMU(内存管理单元)的地址转换机制,完成虚拟空间带地址空间的映射;
(3).虚拟内存的思想:虚拟内存的思想是允许程序占用的空间超过内存的大小,把程序划分为大小固定的页,由操作系统根据程序运行的位置把正在执行的页面调入内存,其他程序依旧存储在硬盘上,也叫写时复制;操作系统根据内存配置决定一次加载多少页面到内存;
2. 虚拟内存
为了更好的管理内存资源,虚拟内存必须为每个进程提供一个大的(确保进程可以顺利的运行),一致的(我们应该对需要进行运行的进程一视同仁)和私有的(确保不同的进程不会意外的写进另外一个进程的存储空间造成错误)存储空间。
- 虚拟内存的作用与缺点
虚拟内存简虚存比实存有以下好处:
(1) 扩大地址空间。无论段式虚存,还是页式虚存,或是段页式虚存,寻址空间都比实存大。
(2)内存保护。每个进程运行在各自的虚拟内存地址空间,互相不能干扰对方。另外,虚存还对特定的内存地址提供写保护,可以防止代码或数据被恶意篡改。
(3)公平分配内存。采用了虚存之后,每个进程都相当于有同样大小的虚存空间。
(4)当进程需要通信时,可采用虚存共享的方式实现。
不过,使用虚存也是有代价的,主要表现在以下几个方面:
(1)虚存的管理需要建立很多数据结构,这些数据结构要占用额外的内存。
(2)虚拟地址到物理地址的转换,增加了指令的执行时间
(3)页面的换入换出需要磁盘I/O,这是很耗时间的。
(4)如果一页中只有一部分数据,会很浪费内存。
什么是缓存
缓存是CPU的一部分,它存在于CPU中
缓存是为了解决CPU速度和内存速度的速度差异问题
内存中被CPU访问最频繁的数据和指令被复制入CPU中的缓存,这样CPU就可以不经常到象“蜗牛”一样慢的内存中去取数据了,CPU只要到缓存中去取就行了,而缓存的速度要比内存快很多
因为缓存空间较小, 如果CPU找不到 会去内存去寻找,那么这样速度就会慢很多 不过CPU会将访问的数据存入缓存 以便下一次寻找
缓存中的数据要经常按照一定的算法来更换,这样才能保证缓存中的数据是被访问最频繁的
缓存替换算法
(1)随机算法(RAND)。随机算法就是用随机数发生器产生一个要替换的块号,将该块替换出去,此算法简单、易于实现,而且它不考虑Cache块过去、现在及将来的使用情况。但是由于没有利用上层存储器使用的“历史信息”、没有根据访存的局部性原理,故不能提高Cache的命中率,命中率较低。
(2)先进先出(FIFO)算法。先进先出(First In First Out,FIFO)算法是将最先进入Cache的信息块替换出去。FIFO算法按调入Cache的先后决定淘汰的顺序,选择最早调入Cache的字块进行替换,它不需要记录各字块的使用情况,比较容易实现,系统开销小,其缺点是可能会把一些需要经常使用的程序可(如循环程序)也作为最早进入Cache的块替换掉,而且没有根据访存的局部性原理,故不能提高Cache的命中率。因为最早调入的信息可能以后还要用到,或者经常要用到,如循环程序。此法简单、方便,利用了主存的“历史信息”,但并不能说最先进入的就不经常使用,其缺点是不能正确反映程序局部性原理,命中率不高,可能出现一种异常现象。
(3)近期最少使用(LRU)算法。近期最少使用(Least Recently Used,LRU)算法是将近期最少使用的Cache中的信息块替换出去。该算法较先进先出算法要好一些,但此法也不能保证过去不常用将来也不常用。
LRU算法是依据各块使用的情况,总是选择那个最近最少使用的块被替换。这种方法虽然比较好地反映了程序局部性规律,但是这种替换方法需要随时记录Cache中各块的使用情况,以便确定哪个块是近期最少使用的块。LRU算法相对合理,但实现起来比较复杂,系统开销较大。通常需要对每一块设置一个称为计数器的硬件或软件模块,用以记录其被使用的情况。
实现LRU策略的方法有很多种。简单介绍计数器法、寄存器栈法及硬件逻辑比较对法的设计思路。
计数器法:缓存的每一块都设置一个计数器。计数器的操作规则如下:
- 被调入或者被替换的块,其计数器清0,而其他的计数器则加1
- 当访问命中时,所有块的计数值与命中块的计数值要进行比较,如果计数值小于命中块的计数值,则该块的计数值加”1”;如果块的计数值大于命中块的计数值,则数值不变。最后将命中块的计数器清为“0”
- 需要替换时,则选择计数值最大的块被替换。
(4)最优替换算法(OPT算法)。使用最优替换算法(OPTimal replacement Algorithm)时必须先执行一次程序,统计Cache的替换情况。有了这样的先验信息,在第二次执行该程序时便可以用最有效的方式来替换,以达到最优的目的。
前面介绍的几种页面替换算法主要是以主存储器中页面调度情况的历史信息为依据的,它假设将来主存储器中的页面调度情况与过去一段时间内主存储器中的页面调度情况是相同的,显然,这种假设不总是正确的。最好的算法应该是选择将来最久不被访问的页面作为被替换的页面,这种替换算法的命中率一定是最高的,它就是最优替换算法。
要实现OPT算法,唯一的办法是让程序先执行一遍,记录下实际的页地址流情况。根据这个页地址流才能找出当前要被替换的页面。显然,这样做是不现实的。因此,OPT算法只是一种理想化的算法,然而它也是一种很有用的算法。实际上,经常把这种算法用来作为评价其他页面替换算法好坏的标准。在其他条件相同的情况下**,哪一种页面替换算法的命中率与OPT算法最接**近,那么它就是一种比较好的页面替换算法。
(5)最少使用算法(LFU算法 Least Frequently Used Algorithm)。选择最少访问的页面作为被替换的页面。显然,这是一种合理的算法,因为到目前为止最少使用的页面,很可能是将来最少访问的页面。该算法既充分利用了主存中页面调度情况的历史信息,又正确反映了程序的局部性。但是,这种算法实现起来非常困难,它要为每个页面设置一个很长的计数器,并且要选择一个固定的时钟为每个计数器定时计数。在选择被替换页面时,要从所有计数器中找出一个计数器值最大的计数器。
内存管理方式
(1)块式管理:把主存分为一大块一大块的,当所需的程序片段不在主存时就分配一块主存空间,把程序片段load入主存,就算所需的程序片段只有几个字节也只能把这一块分配给它。这样会造成很大的浪费,平均浪费了50%的内存空间,但是易于管理。
(2)页式管理:把主存分为一页一页的,每一页的空间要比一块一块的空间小很多,这种方法的空间利用率要比块式管理高很多
(3)段式管理:把主存分为一段一段的,每一段的空间又要比一页一页的空间小很多,这种方法在空间利用率上又比页式管理高得多,但是也有另外一个缺点。一个程序片段可能会被分为几十段,这样很多时间就会被浪费在计算每一段的物理地址上。
(4)段页式管理:结合了段式管理和页式管理的优点。把主存先分成若干段,每个段又分成若干页。段页式管理每取一次数据,要访问3次内存
来源:https://blog.csdn.net/weixin_42446419/article/details/100032753