浅谈操作系统(一)

最近在跟着王道老师学习操作系统,收获颇丰,为防止易忘,对学习内容进行一个总结概括。有不对之处,还望大家评论指正,互相学习。

一 前言

我们知道一个计算机的组成大体就分为软件和硬件,用户或者程序员通过应用层软件程序去调用计算机的硬件功能,比如我们打开摄像头、磁盘读写等。计算机硬件处理的核心CPU还有存储器等实际上是通过二进制机器指令进行功能操作,如果我们(程序员)直接对CPU和内存控制器进行操作,其难度和复杂度可想而知。然而实际上,我们都是通过高级语言(比如C、java)去进行操作,而不用关心其中的一些复杂操作,在这里,操作系统就起着巨大作用,他会将编译好的指令按照相应的地址和顺序从外存中调入内存,然后让CPU去执行这些指令。当然,操作系统的功能不止这些,比如我们一边听歌一边写代码,然后挂着DNF,打开谷歌浏览器,而且还开着摄像头跟女朋友视频,在实际体验上是非常爽的,操作系统在这里又起着重要作用,比如对内存的虚拟扩充技术,因为内存可能只有4G,而实际上这些应用的内存的需求可能是6G,至于为什么可以出现这种类似与内存扩充的现象后续会讲,在这里操作系统还起着CPU管理的作用,比如这个计算机是4核的但是他运行了不止4个程序,这种”并行“是如何实现的也是后续再阐述。
好了,现在应该知道了操作系统的重要性了,现在也可以把操作系统概括为用户和硬件之间的一个软件翻译者或者硬件管理者与硬件执行者这种角色。上一张王道老师视频中的一个计算机结构图。
浅谈操作系统(一)_第1张图片

二 操作系统学习框架

前面简单的说了操作系统在计算机中扮演何种角色,这节将从不同角度,更加概括性的说明操作系统的作用。
首先是对于用户来说,操作系统提供的功能为命令接口、程序接口和GUI(图形用户界面)。对于命令接口用户可以直接使用,比如linux系统中的终端。程序接口是程序使用的,当然也可以说是程序员使用,程序接口指的是操作系统提供给应用程序的一个封装函数也可以称之为系统调用。最后一个GUI相信大家就很熟悉了,比如windows系统中的各种图标、显式文件夹等。
其次,通过第一章我们了解到,操作系统还对系统硬件资源进行管理,所以我们也可以从硬件资源这块对操作系统的功能进行分析。那么操作系统需要管理哪些资源呢?处理机{cpu)、存储器{内存}、文件系统、设备,主要就是这四方面。那么我们就一个例子来进行一个描述,比如我想登录QQ,首先在各文件夹中找到QQ安装的位置(文件系统管理),然后关机点开QQ.exe运行QQ(内存管理)、接着QQ可以正常运行(CPU管理),最后,开始和女朋友视频(设备管理),以上这些操作对于我们用户来说是不可见的,那么在这里操作系统的左右就很明显了,它使得底层相对于上层是不透明的,也就上层是看不到下层如何运转的,当然上层也不care底层如何运作。
那么,通过上述对操作系统功能的一个概括,我们对操作系统的学习就可以规划为四个部分:处理机管理、存储器管理、文件管理和设备管理。
在学习上述四个部分之前,还有一个重要的内容,解释操作系统的内核。内核是什么呢?内核是操作系统的一部分,也是操作系统的核心,内核它实际上就是一个软件程序,那么它实现了什么功能呢?首先,我们应该已经了解到,操作系统对硬件直接的管理,并封装成系统调用给应用程序使用,这里主要就是通过内核程序来实现的,所以内核对硬件相关联的作用是时钟管理、中断处理和原语。时钟对于计算机的作用不言而喻,它可以实现计时功能。中断处理后续会讲到。那么什么是原语呢,首先得了解原子操作,这里不多做叙述,原语其实就是一道程序(不是一行),处于操作系统最底层、最接近硬件的部分,它的运行具备原子性,是一气呵成不会被打断的,当然它也不会运行太长时间。内核功能不止上述的三种功能,还包括进程管理、存储器管理、设备管理,不同的系统的内核有不同的功能,但是前面所述的三种是必须的。另外还有微内核和大内核之分,微内核大多数用于嵌入式操作系统。直接上一张王道老师的图吧,清晰明了。
浅谈操作系统(一)_第2张图片

三 处理机管理

描述处理剂管理之前得先有几个问题,操作系统管理处理机做什么事?在回答这个问题之前首先了解下进程的定义。
首先,进程是资源分配和调度的基本单元。进程的组成包括:程序段、数据段、PCB。所谓的创建进程实际上是创建进程PCB,PCB是进程存在的唯一标志。那么PCB是什么呢,process control block,进程控制块。它的内容大体包括:进程描述信息、进程控制管理信息、资源分配清单、处理机想关信息。对于不同的操作系统可能有所区别。进程描述信息指的是进程标识符pid和用户标识符uid,pid用于标识这个进程,uid的作用体现在进程的权限上。进程控制和管理信息包括:进程状态和进程优先级,进程状态有三态(运行态、就绪态、阻塞态)和五态之分(另包括创建态和终止态),如果更加全面的话还包括挂起态,这里不多做描述,自行百度。资源分配清单包括:程序段指针、数据段指针、键盘、鼠标等。处理机相关信息为各种寄存器值,当进程切换时需要把进程当前的运行情况通过各种寄存器记录下来保存在PCB中,一般寄存器包括PC(process count 程序计数器)、CCR(condition code register 条件码寄存器)、IR(Index register 地址寄存器)、DR(data regisiter数据寄存器)、SP(stack point栈指针寄存器)等。当然PCB中记录的东西可能不止这些,需要大家自己补充,直接上一张图清晰明了。浅谈操作系统(一)_第3张图片
介绍完了进程,我们再来回答这一小节开头提出的问题:“操作系统管理处理机做什么事?”答案是操作系统管理处理机该执行那些进程,专业点讲就是调度。那么什么时候进行调度?为什么需要调度呢?也就是调度的目的是什么呢?还有怎样进行一个合理的调度?这又涉及到怎样才算这个调度合理?(妈耶,头大)回答问题之前,我们还是先理清思路,cpiu是如何处理进程的,回答这个问题好麻烦,需要从进程的存储空间、程序编译汇编连接执行、进程的组织形式等说起,在这里就简单的描述下吧,cpu访问内存(或者高速缓冲)中进程的PCB中相关信息(也就是PCB中的数据段指针、程序段指针还有和上下文相关的额寄存器信息),去外存中提取相关机器指令(就理解为代码好了)到CPU中,然后执行。这就是一个很简单通俗的过程,再通俗点,就是CPU访问内存,而内存中有好多进程,CPU先执行哪一个呢,这就存在一个调度,我们称之为低级调度。那么有低级调度肯定有中极调度和高级调度。高级调度指的是将进程从外存放进内存,中级调度是当内存中进程太多导致内存使用紧张,那么就需要将一些进程的作业(程序段和数据端段,我是这么理解的)移除内存,给内存腾空间,但是它的PCB必须留在内存,因为我们还要把他调回来,PCB中会存放相关的信息,这些PCB连成的队列就称之为挂起队列。那么这里选取那个进程挂起(也就是之前所述的操作)就是所谓的中级调度。好了,上图。浅谈操作系统(一)_第4张图片
介绍完调度的相关概念,我们就开始回答之前提出的几个问题,
第一:“神么时候进行调度”,通过前面的低级调度、中级调度和高级调度,我们可以分为这几种情况:1;当前进程因为异常而终止或者正常终止或者主动请求阻塞(没有获得相关资源,比如IO)而主动放弃处理器。2:分给进程的时间片用完(这涉及到调度算法后面有讲)、CPU有更紧急的事处理(中断)、其他优先级更高的进程进入就绪对流请求CPU而被动放弃CPU。以上两条(主动和被动)事针对于低级调度描述的,当然我们现在只讨论低级调度。回答了这个问题,又一个问题来了,我们前面有说过一个原语也就是原子操作的概念,它事一气呵成的不能被打断,所以如果程序处于在原子操作阶段,他是不能被调度切换的,当然这个原子操作的时间会很短。
第二:“为什么需要调度呢?也就是调度的目的是什么呢?”,对CPU来说,它的执行速度是非常快的,主频能达到G的级别,而我们一般的固态硬盘只有几百兆读写速度,所以这就造成了CPU在等待IO操作,而这时候操作系统当然不乐意了,人们要求的高效并没达到,所以C操作系统它会使劲的榨干CPU不会让它偷懒等待别人,这时候操作系统就是用调度,让这个让CPU等待的进程退出CPU,进入阻塞队列,让CPU去执行就绪队列中正在等待CPU资源的进程,这样就达到了一个比较高效的目的。
第三:“怎样进行一个合理的调度?这又涉及到怎样才算这个调度合理?”,什么是一个合理的调度?这里面就这涉及到几个评判指标:CPU利用率、系统吞吐量、周转时间(周转时间、平均周转时间、带权周转时间、平均带权周转时间)、等待时间、响应时间。这里不过多介绍,免得显得繁琐。调度的方法有很多种,比如先来先服务(FCFS)、短作业优先(SJF)、高响应比有限(HRRN)、时间片轮转、优先级调度和多级反馈队列等。先来先到服务(FCFS)字面理解很简单,先来的就先占用CPU,使用完了就让出,这种比较公平,不会导致“饥饿”,但是对短作业不利。短作业优先(SJF)/短进程优先(SPF),最短的作业/进程优先(“最短”指的是要求服务时间最短),SJF和SPF分为抢占式和非抢占式,非抢占式是进程运行完才切换,抢占式是指取当前所有进程中的最短运行时间的进程运行,这可能打断正在运行的进程,因为正在运行的进程剩余时间可能大于这个进程的总运行时间。一般默认是非抢占式的。缺点是对长嘴也不利,可能产生饥饿。高相应比优先(HRRN),非抢占式算法,所以只有在当前进程执行完,需要调度时计算作业/进程的相应比,选择相应比高的为其服务。相应比为(等待时间+运行时间)/运行时间。这个算法不会导致饥饿。时间片轮转,由程序分配时间片给进程去占用CPU,属于抢占式算法,有点事公平,缺点是切换频繁不区分优先级,时间片太长或者太短都有影响。优先级调度,由抢占式和非抢占式之分,里面涉及优先级调整、优先级设置等问题。优点是区分优先级适合实时系统,缺点是可能会导致饥饿。多级反馈队列,属于抢占式算法,它结合了FCFS算法、时间片轮转算法(动态时间片)、优先级调度算法(动态优先级),使得进程可以区分优先级、可以公平的占用CPU。具体的过程可以自行百度学习。这里贴一张图辅助理解。浅谈操作系统(一)_第5张图片
以上便是针对处理机管理提出的三个问题的回答。总结下,CPU管理的核心是进程调度,对象是进程,目的是快速高效公平的运行进程。前面讲述了进程的定义,调度的时机,以及六种调度算法。当然实际上操作系统对于CPU的管理不止这些,还有进程的同步与互斥等。这些放在另外的专题讲解。
好了,关于处理机管理先就说这么多吧,有补充在添加,下一小节讲说明存储器管理。

四 内存管理

我们知道CPU的数据指令获取来源于内存,而内存的大小是有限制的,处理上述提到的通过调度(中级调度)来缓解内存的压力外,对内存的合理组织形式也相当重要,当然也包括之前所提到的虚拟扩充技术。在本小结开头先对内存管理做一个概括,内存管理包括内存空间的分配与回收、内存空间的扩充、地址转换、存储保护。后续也将就这个几个方面进行阐述。
那么在仅从阐述之前,先了解下一个C程序是如何被执行的。从程序员的角度来说,一个程序经过编译、汇编、链接之后,生成可执行文件才可以被装入内存。链接的过程讲编译后形成的一组目标模块以及所需库函数连接在一起,形成一个完整的装入模块,由装入程序装载进内存。这里的装入程序可以分为三种,绝对装入、可重定位装入、动态进行时装入。他们的不同之处在于绝对装入使用的是绝对地址,可重定位装入使用的是逻辑地址,动态进行时装入指的是吧地址转换推迟到程序真正要执行时才进行,使用的仍是逻辑地址。同样的对于链接也有三种方式:静态链接、装入时动态链接和运行时动态链接。具体的自行百度,这里不多做赘述。
对内存空间的扩充可以通过覆盖技术、交换技术和虚拟存储技术。覆盖技术存在于早期的操作系统,它是将程序分成不同的几个段,将非配个这个程序的内存段非为固定区和覆盖区,常用的程序段(比如main函数)房子啊固定去,不常驻内存的程序段放在覆盖区,顾名思义,当该CPU需要某个程序段而该程序段不在内存时,操作系统将该程序段取出放进内存中的覆盖区,直接覆盖原本的程序段。以此解决“程序大小超过物理内存大小总和”的问题。交换技术的设计思想时在内存紧张时,系统将内存中某些进程暂时患处外存,把外存中某些已具备运行条件的进程换入内存,这是不是和上一小节所述的中级调度相似?现在回忆一下,中级调度时内存于磁盘之间的调度,操作系统会把进程的作业调出内存,但是该PCB留在内存,而这些进程的状态就时所谓的挂起态,根据他们呢之前所处的状态又可分为就绪挂起态和阻塞挂起态。那么问题来了,交换出去的作业他们放在那里呢?当然不是磁盘中乱放,磁盘中有固定的一块连续的存储空间用于存放这些作业,我们称之为交换区(对换区),而另一部分就是文件区,对换区的IO速度比文件区的IO速度快,文件去追求空间利用率而对换区追求更快的读入读出,所以文件区采用的是离散存储而对换区采用的是连续存储。交换区的大小如何分配呢,一般情况下,当内存小于4G时,交换区不少于2G,当内存大于4G小于16G时,交换区不小于4G,当内存大于16G小于64G时,交换区不小于8G。内存大于64G,交换区不小于16G
内存的分配管理分为两种:连续分配管理和非连续分配管理。连续分配方式分为单一连续分配、固定粪污分配和动态发你去分配。单一分配用于早期的操作系统,即一道进程占用整个内存空间,这种方式实现简单、无外部碎片,可以采用覆盖技术扩充内存,但是这种方式只适用于单任务操作系统,存储器利用率低,有内部碎片。固定区分配是建立一个分区说明表,记录分区的代销、起始地址、状态。这种非那方式优点实现简单,五外部碎片,但是局限性很大,分区太大会产生内部随便,分区太小,大文件无法装入。动态分区分配时根据文件的大小来分配分区。动态分区分配没有内部碎片,有外部碎片,可以通过紧凑来时外部碎片组合。在动态分区分配时,会有很多不相邻的空闲分区满足文件的需求,那么如何选择分区呢,这里也涉及到物种算法:首次适应算法(FF)、最佳适应算法(BF)、最坏适应算法(WF)、邻近适应算法(NF)。首次适应算法如字面意思。从最低地址开始查找,找到第一个满足大小的空闲分区。最佳适应算法指的是使用满足需求的最小的空闲分区,提高利用率。最坏适应算法刚好相反,使用满足要求最大的空闲分区,这样多出来的部分不至于太小。邻近适应算法是首次适应算法的改进,它是从记录上一次查找的位置开始查找,以减小查找开销。
上述讲了连续分配管理方式,其中包括集中不同的方法,由于其需要连续存储的需求,这些方法不可避免的产生了一些内部或者外部碎片。于是人们便想到如果不用连续存储,使用一种特殊的数据结构,来实现离散存储是否能解决碎片的问题?以下便通过基本分页管理、基本分段管理和段页式管理继续宁阐述。介绍基本分页存储前,首先要知道什么是分页?将内存空间分为一个个大小相等的分区(比如4KB),每个分区都有一个编号,即页框号,页框号从0开始。页框=页帧=内存块=物理块=物理页面。操作系统以页框为单位为各个进程分配内存空间。为了能知道进程的每个页面在内存中的相对应的位置,操作系统为每个进程建立了一张页表(PCB中)。页表有页号和块号组成。进程的逻辑地址空间对应的就是页号,块号对应的内存中的块首地址。由于每个块的长度相同,即可很容易计算出物理地址。分页存储的逻辑地址结构为页号和页内偏移量组成,在32位系统中,假如页面带线啊哦位4K,那么需要12个bit区表示,而另外20位就可以表示页号。虽然在逻辑地址中,这种结构是二维的,但是换算成物理地址,我们得到的就是一个确切的一维地址,这不同于基本分段存储的寻址方式。通过以上描述,介绍了一种不同于连续存储管理的内存管理方式,这提高了存储器的利用率。为了防止忘记前面的,把前面的也概括下,首先CPU要运行一个进程,操作系统首先会检查进程PCB在不在内存里,如果不在,那么就启动中级调度,将其调入内存。当然此时这个进程具备一切的条件,不然会进行一系列的六种低级调度,此时CPU获取其PCB,取出相关的寄存器回复现场,然后获取PCB中的页表去获取相关指令或数据。那么我们上面所讲的内存管理就是在这个获取指令上面,因为获取指令需要物理地址,而物理地址的计算和内存的存储管理方式相关,在连续存储管理中有绝对粗出、可重定位存储、动态分区存储。在非连续存储管理中有基于分页存储管理、基于分段存储管理方式还有段页式存储管理。不同的方式计算物理地址方法不同,资源利用率也不同。上述所讲的是基于分页式存储。在基于分页存储中还有一个知识点,那就是快表还有两级快表。快表存放于高速缓冲中,它的作用是减少内存中页表查找时间,具体的自行百度。
和基本分页类似的还有一种请求分页管理方式,这也是内存管理方式中的一种。它与基本分页管理方式不同的地方在于党所访问的信息不存在时,由操作系统负责将所需信息从外存调入内存,若内存不够,由操作系统将内存中暂时用不到的信息换到外存。相比于基本分页管理,请求分页有几点不同:一:请求分页的页表包括:页号、内存块号、状态位(是否已装入内存)、访问字段(存放近期访问记录)、修改位(调入内存后是否有修改)、外村地址(页面在外存的存放地址)。二:缺页中断机制,当需要访问的页面不在内存时,会产生一个缺页中断,通过中断处理程序进行调入,此时集成进入阻塞。如果内存没有空闲块,则操作系统选取一个页面进行替换,如果页面的修改位标记,则需要将该页面重新写入外存,肉则可以直接覆盖。那么在这个时候,就出现了一个问题,在请求分页管理方式中,如果发现需要访问的页面不在内存中,需要中断调入时发现没有空闲块,那么需要置换出内存中的页面,那么置换那一部分页面呢?这里就涉及到五种置换算法:最佳置换算法(OPT)、先进先出置换算法(FIFO)、最近最久未使用置换算法(LRU)、时钟置换算法(CLOCK)和号进行时钟置换算法。最佳置换算法:每次选择淘汰的页面将是以后用不使用或者在最长时间内不被访问的页面。这样可以保证最低的缺页率。具体做法是遍历当前位子后面需要访问的内存块,找到进程所拥有内存块中未来最久或者没有被访问的页面,将其置换。由于操作系统无法预判接下来会要访问哪些页面,所以这个算法是无法实现的。先进先出置换算法:每次选择淘汰的页面是最早进入内存的页面,很容易理解,算法性能差。最近最久未使用置换算法:每次淘汰的页面时最近最久未使用的页面,实现方法就是访问该页表中的访问字段,选择最久的那个没有被使用的页面,算法开销大。时钟置换算法:不怎么好描述,关于改进型时钟置换算法也可以自行百度或者看看王道老师的视频。最后啰嗦一句,请求分页是虚拟内存阔技术实现的手段之一。其他的还有请求分段管理和请求段页式管理。浅谈操作系统(一)_第6张图片
一张总览图概括下本节内容吧。本文着重讲的是基本分页存储管理和而虚拟内存技术中的请求分页管理相关的置换算法。
浅谈操作系统(一)_第7张图片

五 小结
由于作者技术水平和写作水平有限,本文章只是用于总结自己所学知识加强巩固,如果这篇文章能对读者有所帮助,万分荣幸。如果您在阅读过程中发现相关的技术性错误,欢迎指正,我们呢共同学习。另外还有文件系统和设备驱动在下一篇文章中再阐述。

另:再次鸣谢王道论坛的操作系统课程,收获很大。b站和mooc可搜!

你可能感兴趣的:(操作系统,嵌入式,内核)