CHS_02.1.4+操作系统体系结构 二
操作系统的结构 上篇文章我们只介绍过宏内核 也就是大内核以及微内核
今年大纲又增加了分层结构 模块化的结构以及外核这种比较特别的操作系统结构
那个人认为这个部分如果考的话 肯定就是对各种操作系统结构特性的一个考察
以及每一种结构 它具有什么优点或者缺点 选择题大概率是以这样的角度去命题的
所以这给大家总结了各种操作系统结构的特性 以及他们的这种设计思想是什么
各自的优点缺点是什么 这个图里边标新号的这些部分是我认为更有可能在选择题当中作为选项的
一些点红色型号的是全新的内容 黄色型号的是涉及到大内核和微内核 所以都是我们比较熟悉的老内容
好 接下来我会给大家解释这个总结图里边的每一句话是什么意思 帮助你加深印象
首先来看分层结构的操作系统 先看个图 这是
分层结构的操作系统
最底层是硬件 最上层是用户接口 操作系统的内核会被分为多层 就像一个洋葱一样
每一层 它可以单向的调用更低一层提供的接口 注意 每一层它只能调用相邻的那一层所提供的接口
比如在这个图里面分为了一层二层和三层这样的三个层次 那一层它最接近于硬件
只有第一层可以直接操作硬件 而第二层它只能使用第一层提供的一些功能接口
第三层只能使用第二层提供的功能接口 每一层只能去调用更低的相邻内层提供的功能
而不能跨层的调用好 那这种分层的设计思想造成了这种结构的一些优点和缺点
先看优点 首先 这种分层结构很便于调试和验证
只需要自己向上的逐层调试和验证就可以了 因为每一层它只会使用到相邻的低层所提供的功能
因此 这种分层结构的操作系统内核开发完了之后 我们得调试验证它的功能是否正确 对吧
那么调试验证就可以这么做 首先 第一层 它只会使用到底层的硬件
而硬件厂商在出厂这个硬件的时候 他肯定已经保证硬件的特性没问题了
所以第一层只需要管我这一层当中的一些代码功能 去验证一下 调试一下都ok 那么第一层的调试就结束了
好 接下来 在对第二层进行功能的调试和验证 由于第二层 它只会使用到第一层提供的一些功能
而刚才我们已经调试过第一层的这些功能和代码了 确保它是没有问题的 因此第二层的调试和验证就可以基于正确的第一层来进行
那么我们一层一层的往外调试 先保证更低层的功能特性是调试过的
被验证是ok的 然后再来调试更高一层 那这样的话操作系统分层开发完了之后
一层一层的来分层调试 是不是就变得很方便了 就可以使得软件测试的这个过程变得很清晰明了
所以这是他的第一个优点 便于调试和验证 而第二个优点易于扩充和维护
各层之间的调用接口清晰固定 因为这种分层结构的操作系统内核在设计的时候就肯定得先设计好
成语层之间的调用接口是什么样的 这个函数名叫什么 以及调用的参数需要提供哪些 各个参数的含义是什么
每一个调用又会给你返回什么东西 这些层与层之间的调用接口都是在最初设计的时候就已经规定好的
所以 由于这些层间的调用接口固定不变 因此如果我们要在原有的两层之间
在新加一层是不是也是ok的 我们只需要保证新加的这一层向更上层提供同样的这个接口
以及新的这一层对于更下层的这个接口的使用 是不是以前这个更低层已经实现了
所以我们要在两层之间再扩充新的一层是很简单的 只需要保证原来定义的这个接口不变就可以了
那由于这种层间的接口固定 所以也比较方便维护好 说完了他的优点 再来看他的缺点
分层结构的操作系统 它只能调用相邻的低层 但是我们有时候又难以合理的定义各层之间的边界
什么意思呢 a功能有可能会调用b功能 而b功能有时候你难免也需要使用到a提供的功能
比如进程管理 有时候需要使用到内存管理相关的一些功能 而内存管理相关的功能
有时候又需要使用到进程管理提供的一些东西 所以这种很严格的只能由高层调用 低层的这种规定是不是就很不灵活
有时候我们很难把操作系统内核的这些功能把它严格的这种一层一层的给它分出来
同时我们还要保证只能高层调用低层 这个很难 所以这是他的第一个缺点
好 第二个缺点就是效率低 由于不可以跨层调用 所以系统调用执行的时间会很长
比如说我是一个用户 我用户进行系统调用 那现在我的这个系统调用
也许他只需要使用到最底层提供的一个功能 但是最上面这一层无法直接调用最底层提供的这个功能接口
我只能一层一层的往下传递 就有点类似于a和d要说一句话 但是分层结构就规定a不能直接和d讲话 他只能先告诉b b在告诉c c在告诉
同时 如果地要给a回话 那么地址能先给c回话 c再给b回话 然后b再给a回话
a和d之间不可以直接的进行相互的调用以及返回结果 所以这就会导致系统调用的时间执行时间会变长 效率变低
而这是分层结构 特别注意这两个点 我认为更有可能考接下来模块化的这种操作系统结构
模块化是一种很经典的程序设计思想
会把操作系统的内核
划分为多个模块 然后各模块之间相互协作着工作 比如说把操作系统内核分为进程管理
存储器管理 文件管理 以及什么设备驱动程序等等 分为多个模块 每个模块又可以进一步划分为子模块
整个内核有主模块和可加载内核模块来组成 那主模块就是
必不可少的 最核心 最重要的那些模块 没有这些模块 操作系统就无法运行
比如说 进程管理 内存管理 这些重要的模块共同组成了所谓的主模块
而可加载内核模块是可以动态加载到操作系统内核当中的 比如设备的驱动程序
就属于可加载的内核模块 我有这个驱动程序 还是没有这个驱动程序 并不会影响到系统能不能正常运行 对吧
它只是会影响到系统的一个可拓展性 如果我们加载了这个驱动程序的模块
那么系统就可以支持新的设备 所以可加载内核模块 算是一个锦上添花的东西
好 来 看一下模块化操作系统的优点 第一个优点 模块之间逻辑清晰 易于维护
我们是按逻辑功能进行模块的划分的 有的模块专门管进程 有的模块专门管内存
所以 逻辑清晰 易于维护 同时我们只需要确定每个模块之间的接口 就可以多模块同时进行开发
比如我的进程管理这个模块 需要对外暴露123这样的三个功能接口
那只要我们规定好这三个功能接口函数的名字是什么 参数列表是什么 以及返回知识什么
那么即便我的这个模块现在还没有完成开发 那其他的模块是不是也可以就是同时并进啊
如果我要使用到你这个模块提供的这些功能接口 那么我按照我们提前约定好的这些模块之间的接口来开发 是不是就ok了
好 所以只要确定了各个功能模块之间的接口 之后 就可以多个模块同时并行的开发
这是第一个优点好 第二个优点 这种模块化的操作系统内核通常都可以支持动态的加载一个新的内核模块
如果想让你的操作系统支持一个新的设备 那么把这个设备驱动程序作为一个新的内核模块加载到操作系统当中 是不是就ok了
以及如果要让操作系统支持一个新的文件系统 那么我们把新文件系统的这些代码数据给它作为一个新的内核模块加载到操作系统内核里面 所以这种特性可以使得操作系统的适应性
增强加载一个新的模块 不需要重新编译整个内核啊 这是第二个优点
第三个优点 任何模块之间都可以直接调用 其他模块无需采用消息传递进行通信 效率高
什么意思呢 各个模块之间我要使用你的功能就直接掉你的函数就可以了
就跟你平时写代码直接调一个函数一样 那这种方式可以使得功能的调用效率非常高
相比之下 在v内核结构的操作系统当中 就需要使用到消息传递的这种方式
来调用其他模块提供的一些功能 我们一会再来解释 而这是第三个优点 各个模块之间可以直接相互调用 效率高
说完优点看他的缺点缺点低模块之间的接口定义未必是合理实用的
就是说 我这个进程管理这个模块 本来只提供这样的三个功能 但是开发的过程当中 你可能会发现
哎 其他模块好像还需要使用到一个新的功能 对吧 所以由于各个模块之间可能相互调用会比较多
因此 在开发各个模块的时候 这个接口定义可能是比较难的 另外 模块之间相互依赖难以调试和验证
就是说我这个模块之间你调我 我调你 我们相互调对吧 那这样的话如果我调试的时候发现
我这个模块好像功能出了问题 那到底说我模块本身的问题还是我调用的这个东西它的问题
还是说我掉了他然后他又掉了我之后才产生的问题 所以就会导致这个调试和验证会比较困难
那相比之下这种分层结构其实它也是一种模块化的设计思想 对吧 每一层就是一个模块嘛
但是分层结构的这些模块之间有一个很清晰的 单向依赖的关系
高层可以调用更低一层 所以分层结构在调试和验证的时候显然就会更容易一些
好 这是模块化的缺点 重点注意打红星的这两个特点好 接下来宏内核和微内核 这是我们比较熟悉的东西
宏内核和微内核
宏内核呢 就是要把所有的这些系统功能都放在内核里边 事实上 宏内核 它也采用了模块化的设计思想
我们给了这样的一个图 在内核当中有进程管理 存储管理 设备管理 以及和硬件关系最紧密的什么中断处理 原语始终管理等等这所有的这些功能
都放在内核里边 整个内核里边的各种功能之间也是可以直接相互调用的 就跟普通的函数调用一样
那相比之下 微内核只会把最基本的 与硬件最紧密的一些功能放在内核当中
大多数的功能会被放在微内核之外 那在这种情况下 功能和功能之间的调用就没有那么方便了
进程管理想要调用存储管理相关的功能 它只能通过消息传递的方式来进行
进程管理的模块向微内核发送一个消息 那这个消息里边就是指明了 哎 我想要调用谁
我给他的这个调用参数是什么 好 然后会由微内核的进程间通信相关的这个功能
把他的这个消息传递给存储管理这个模块好 然后这个模块接收到进程管理的这个消息之后
他才会处理这个调用的请求 同时如果要返回这个调用的结果 那同样的也是需要通过消息传递的方式
让微内核来协助各个模块之间的这种调用以及返回 那显然直接进行函数调用肯定要比通过消息传递来通信来调用要快得多
好 所以大内核通常性能会更好 而微内核它的性能会更差 那微内核由于内核更小 功能更少
所以对于内核的这个维护是不是就变得更简单 同时内核它越简单 可靠性肯定也越高
另一方面 由于各个功能模块都被放到了内核之外 所以某一个功能模块出错并不会导致整个系统的崩溃
但是对于大内核来说 只要某一个功能模块出错 那由于这些模块之间相互依赖很强 所以内核中任何一个功能模块出错 就有可能导致整个系统内核崩溃
好 那这是大内核和微内核 都是我们比较熟悉的东西好 最后一种操作系统结构叫做外核
外核
这种结构的操作系统非常少见 我在维基百科找了这样的一个结构图 这是硬件
这是内核 这个部分是外核 这是应用程序
应用程序可以通过系统提供的这些库函数去调用普通内核的一些功能
也可以通过库直接去调用外核所提供的一些功能 所以 这种操作系统
它由内核 外核两个部分来组成 那在这种系统当中内核的部分
他只负责进程调度 进程通信等等这些功能 而外核 这个部分会负责为用户进程分配
未经抽象的硬件资源 比如说磁盘的存储空间 内存的存储空间
这些硬件资源都是由外核 来负责管理的 而内核只管什么进程 调度 进程通信这些和硬件资源分配回收无关的这些工作
好 来解释一下什么叫做给用户进程分配未经抽象的硬件资源
我们知道 在普通的操作系统当中 如果用户进程 他想要申请使用一片内存空间
那么给他分配的内存空间是经过抽象的 经过虚拟化的用户进程 他自己看到的视角
似乎是自己拥有了一整片连续的这个内存空间 但事实上 这只是虚拟的地址空间
操作系统内核会把这些虚拟页面映射到实际的物理页框当中 这些物理页框在内存当中通常是离散的
好 所以 普通的操作系统给进程分配的这个内存空间其实是经过抽象的 经过虚拟化的
除了内存空间之外 给进程分配的文件存储空间 外存空间也是经过抽象的
对于进程来说 他觉得自己的文件好像是连续的一个地址空间 对吧
但事实上 这个文件的各个快在磁盘当中很有可能是被离散的存放的
所以 普通的操作系统给用户进程分配的这个磁盘空间也是经过抽象的
那回到外核 这种操作系统 外核 可以给用户进程直接分配未经抽象的这种硬件资源
这样的资源管理策略在有的时候会很有作用 比如一个用户进程 他很有可能知道自己的这一片存储空间
是经常需要随机访问的 一会访问a这个地方 一会访问b这个地方 那如果给这个用户进程分配的磁盘空间
在外存当中是离散的这一块那一块 那么用户进程在随机访问他这些
文件快的时候 是不是意味着这个词头需要来回横跳啊 那这样就会导致用户进程对自己的文件随机访问的这种性能效能变低
因为用户进程的这个文件在外存当中到底被零散的分布到哪些位置
是完全由操作系统来决定的 用户进程自己并不能控制 而如果采用外核 的这种策略
那么 外核 可以直接给用户进程分配未经抽象的硬件资源
也就是说 如果这个用户进程 他知道自己的这个文件需要频繁的被随机访问
那么我就可以向外核 申请 给我分配一整片连续的这个磁盘块
比如说从零号快到1024号快 全部都是我的好 那么用户进程它的这些文件数据直接存放到连续的几个磁盘块当中
那他之后想要随机访问自己这个文件里面的任何一块 是不是磁头移动的 这个距离就会变少
那这样性能就会提升好 所以外合能够给用户进程直接分配一个未经抽象的
系统资源 这在有的情况下是非常有用的 那除了外存的分配 内存的分配也是一样
这是一个物理内存 在有外核 的这种操作系统当中 一个应用程序完全可以向外核 申请
给自己分配连续的一整片物理内存空间 从a到b 这个地址都是我的地盘
外核 给用户进程分配的这个内存区域也是未经抽象的
用户进程看到的就是一片实实在在的物理地址空间 而不是虚拟的经过抽象的地址空间
那外核 除了分配回收这些未经抽象的硬件资源之外 他还需要负责保证
这些硬件资源的使用安全 比如a到b 这个空间已经分配给了这个进程
那么 另一个进程p二想要访问这片区域外核 就需要及时的发现并且制止
同时 原本的这个进程如果要访问a和b之外的其他空间 这个行为也应该被外核发现并制止
所以外核 他分配了这些硬件资源之后 还需要保证这些硬件资源的使用安全
好 那由于给用户进程分配的是不虚拟 不抽象的这种硬件资源 因此用户进程在使用这些硬件资源的时候就可以更灵活
同时 这种硬件资源的分配方法也减少了虚拟硬件资源的硬设层 也提升了效率
什么意思 普通的操作系统给用户进程分配的都是虚拟的硬件资源 比如说虚拟内存
那么 一个用户进程 他在访问自己的地址空间的时候 他只能提供虚拟地址
而操作系统需要去查页表 甚至查二级三级页表 通过多次的仿存才能够把虚拟地址
转换成实际的物理地址 那把这个虚拟地址映射到实际的物理地址
这个映射的过程是不是需要一些时间的代价就会降低系统的整体效率 而对于外核 这种结构来说
我给进程分配的就是a到b这片区域 那只要进程你访问的这个物理空间是在a到b之内 那你就直接访问就行了 操作系统不需要帮你进行地址映射
这就可以使得效率提升啊 这是外核 的优点 那外核 的缺点呢 就是降低了系统的一致性
什么意思呢 在有外核 的这种操作系统当中 有的进程p一他申请的可能也是一个虚拟的地址空间 然后系统还要帮我映射
有的进程p二他申请的可能就是一个物理的地址空间 就操作系统不需要帮他映射
所以给各个进程分配内存 外存的这种策略 以及后续的一些管理是不是就需要考虑到各种各样的情况 所以就降低了系统的一致性 会使得系统变得更加复杂
好 那这就是外核 这种操作系统结构 那到此为止 我们就把所有的这些操作系统结构给捋了一遍
推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习