Linux:冯·诺依曼结构 & OS管理机制
冯·诺依曼结构
我们常见的计算机,比如笔记本,台式电脑。以及一下不常见的计算机,比如服务器,几乎都遵循冯诺依曼体系结构。冯诺依曼体系结构可以说是计算机的灵魂,如果没有这个结构的提出,计算机就不可能走向百姓,以低成本完成高速的运算。接下来,我就为大家讲解这个结构的设计理念。
常见的冯诺依曼体系结构图如下:
我们认识的计算机,都是由一个个硬件组成的,按照以上图片,我们可以分为以下区域:
- 输入设备:包括键盘,鼠标等
- 输出设备:显示器,打印机,网卡,显卡等
- 中央处理器CPU:计算机完成运算的核心部件,包括
运算器
与控制器
- 存储器
对于存储器,我这里要特地说明:
存储器就是内存
虽然计算机绝大部分数据存储在硬盘中,但是硬盘不是存储器,硬盘是输入输出设备,比如从硬盘读取数据,以及把数据写入硬盘
如果我们只考虑数据的流动,我们可以得到以下逻辑关系:
以上关系中,我们可以提炼出两点:
- 所有外设,即输入输出设备,都只能和内存交换数据
- CPU只能和内存交换数据
可见,内存在计算机中起到了核心枢纽的作用,那么为什么要这么做呢?为什么不直接让输入设备和CPU
交换数据,CPU
把计算好的数据直接输出给输出设备,这样不是更快吗???
就像这样:
在这个没有内存的计算机结构中,我们有输入设备
,输出设备
,CPU
,其中CPU
起到计算功能,用于处理计算机的数据。CPU
具有极高的运算效率,但是输入输出设备的读取速度是很慢的,因此很多数据刚被读取到CPU
中,就立马被计算完了,因此CPU
会长期处于闲置状态,这对CPU
的计算资源造成了大量浪费。因此我们要想办法提高CPU
得到数据的速度,也就是输入输出设备
的数据交换的速度。
但是如果想要提高输入输出设备
的效率,那么就要用更好的材料和技术来制作这些设备,如果计算机中所有输入输出设备
的材料以及技术都达到了CPU
级别,那么确实可以让计算机的计算效率不被数据的读取速度影响,但是这将面临计算机成本大幅度提高的问题,有的人工作一辈子也买不起一台计算机。
因此冯诺依曼提出了用内存作为一个中间枢纽的想法:
内存的读取效率介于输入输出设备
与CPU
之间,因此CPU
读取数据的速度,就和内存
输出数据的效率差不多了,只要内存的速度越接近CPU
,那么CPU
的利用率也就越高。
但是这个结构依然有问题,那就是:内存的读取速度又会受到输入输出设备
的影响,内存想要从输入设备
读取数据,最后的数据传输速度不取决于内存,而取决于输入设备
。最后整个计算机的数据传输效率,还不是取决于输入输出设备
的传输效率?
理论上来说,确实是这样的,就好像一个木桶,这个木桶能装多少水,不取决于最长的那一块板子,而取决于最短的那一块板子。
其实,冯诺依曼体系结构中,输入设备
向内存输入数据,不是说CPU
现在要计算啥,内存就从输入设备
提取啥。内存会提前预知CPU
要使用的数据,从而预先把它加载到内存中,这样一来,最后整个计算机的计算效率,就取决于内存的数据传输效率了。至于内存是如何预知CPU
需要计算的数据,这是操作系统OS
的工作了。
通过这样一个冯诺依曼体系结构,我们计算机的计算效率就主要取决于内存
和CPU
了,因此电脑厂家只需要把内存
和CPU
的性能提上来,整个计算机的效率也就上来了。其余的部件,都可以用低廉的材料制作,整个计算机的成本降下来的同时,效率还提高了。因此计算机得以走进普通百姓的家中。
OS管理机制
刚刚我们讲明白了计算机的硬件架构,现在我再来讲一讲计算机的软件架构。计算机中,最重要的软件就是操作系统OS
,在整个计算机的软硬件架构中,OS
的定位是一个管理一切软硬件资源的管理者
。
整个计算机的体系结构如下:
OS对下层硬件的管理
最后三层依次是:OS
,驱动
,底层硬件
。
那么操作系统是如何管理硬件的呢?我先来为大家举一个现实生活中的管理案例。
在大学中你很可能都没有见过你的校长,院长等管理层大人物。但是学校可以知道你有没有挂科,你能不能评奖学金等等。那么这些管理层人员,明明都没有见过你本人,是如何管理你这个学生的呢?
他们在管理你的时候,手中会有你的众多数据,比如:入学年份,年龄,招生方式,各科成绩等等。一旦管理层手中有你的数据了,他们就可以根据你的考试成绩来决定你能不能正常毕业;根据你的各项指标,来决定你能不能评奖学金等等。
这个过程中可以发现,管理的本质不在于对你本人做管理,而在于对你的信息做管理。管理者的核心工作,就是根据你的数据来做决策。
操作系统亦然,操作系统想要管理硬件设备,它管理的并不是硬件本身,而是这个硬件的数据。那么下一个问题就来了,操作系统如何得到硬件的信息???
这就涉及到了驱动
的工作:
每一个硬件设备,都会有自己的
驱动程序
,驱动程序内部有众多关于硬件的信息,操作系统通过管理驱动
来管理硬件
有的人会发现,当你买了一个新的鼠标,新的键盘,第一次插到电脑上,它都要等待一小会才能使用。而且电脑有可能还会在屏幕上显示驱动程序安装成功
这样的提示语句。
其实,每一个硬件在制作的时候,厂家都会在其内部写好一个驱动程序,一旦这个硬件接入到计算机,那么驱动程序就会被操作系统得到,从而进行管理。因此第一次使用一个新的鼠标,键盘的时候,之所以要等一下才能用,就是因为驱动程序还在安装,没有驱动程序,操作系统就无法管理硬件,自然也就无法使用硬件了。
再比如说,有一些硬件,当你接入到计算机后,其可能会提示你:这个设备与计算机不兼容
,计算机怎么知道这个设备和计算机不兼容的?这就是因为接入的时候,操作系统得到了硬件的驱动程序,从驱动程序中检测到了这个设备的信息,从而判断出这个设备与计算机不兼容。
至此,我们就已经讲解完了操作系统是如何管理硬件的,以及是如何得到硬件的信息的。那么我们再来看到一个问题:当我们有众多硬件接入到计算机,操作系统是如何对这些硬件批量管理的?
在讲解这个问题之前,我要提出学习操作系统的六字真言,一切操作系统的管理行为,都遵顼以下六字:
先描述,再组织 \mathbf{{\color{Red} {\huge 先描述,再组织} } } 先描述,再组织
比如说,操作系统想要管理一个鼠标,于是得到鼠标信息后创建了一个结构体,存储鼠标的各项信息:
cpp
struct device
{
int type;
char* name;
//...
}
比如以上结构体就存储了鼠标的名字,类型等信息。于是操作系统通过管理这个结构体来管理这个鼠标。同样的,键盘,显示器,打印机等等设备,在操作系统中都会有自己的结构体,这个结构体描述了硬件的各种信息,这个过程就叫做描述
。
那么操作系统要如何管理这么多结构体?其只需要通过数据结构把这些结构体组织起来即可,比如把这些结构体放到一个链表中,放到数组中,等等。于是操作系通过管理这个链表来管理这一堆结构体,比如说一个鼠标的USB接口被拔掉了,于是操作系统在这个包含了众多结构体的链表中,遍历查找"鼠标"的结构体,然后把这个结构体中描述状态的那个成员,从开启改为关闭。这个把描述硬件的结构体用数据结构连接起来统一管理的过程,就是组织
。
至此,我们就以及讲完了操作系统是如何管理硬件的,汇总如下:
- 操作系统通过
驱动程序
来获得硬件的信息,管理硬件- 操作系统在管理众多硬件的时候,采用
先描述,在组织
的思想,把描述各个硬件的结构体用数据结构组织起来统一管理
OS对上层用户的服务
操作系统管理好硬件,是一种手段,而这个手段的最终目的,是为了给上层提供安全可靠
的服务。
我特意标红了四个字:安全可靠
,那么操作系统又是如何保证自己提供的服务是安全可靠的?我们再看到一开始的计算机体系层次图:
从操作系统向上,依次是系统调用接口
,用户操作接口
,用户
。
请问:==用户可以直接访问操作系统的底层吗?==就拿我们刚刚的例子来说,我们知道每个硬件都有自己的结构体来描述自己,操作系统可以管理这些结构体。那么这些结构体可以直接交给用户管理吗?
很显然,这是很危险的,如果某个用户拿到了一个描述鼠标的结构体,原本这个鼠标是罗技
公司生产的,用户直接修改这个结构体里面对厂商的描述,把它修改为了苹果
公司生产的鼠标,这可就乱套了。因此操作系统不能把底层直接展示给用户,不然是非常危险的。
但是操作系统又要为用户提供服务,于是操作系统给出了很多系统调用接口
,也就是操作系统向上一层。
为了保护操作系统内部的数据,用户只能通过
系统调用接口
来访问计算机
最开始我们就说过,操作系统要为上层提供安全可靠
的服务,而操作系统就是通过隐藏自己的底层,让用户通过系统调用接口
来保护自己的数据,进而保证安全的。
系统调用接口
再往上就是用户操作接口
了,不妨想想,不论你是学习python
,c语言
,C++
,你有直接操作过硬件吗??
其实是有的,比如说python
的print
函数,C++
的cout
,C语言
的printf
函数。这些方法,我们都可以向屏幕输出字符,但是屏幕是一个硬件,想要向硬件输出,就一定要经过操作系统这一层。但是我刚刚说过,用户想要访问操作系统,只能通过系统调用接口
。这么一说,难道各个语言的输入输出函数,都叫做系统调用接口吗???
这是否定的,其实语言层面的输入输出函数,本质上是对系统调用接口
的再封装。现在市面上的操作系统五花八门,比如Android
,iOS
,Windows
,Linux
等等,这些操作系统向上层提供的系统调用接口都是不一样的,但是我们的计算机语言,既可以在Windows
中运行,也可以在Linux
中运行。
在用户操作接口
中,我列举了三个例子:shell外壳
,lib
,部分指令
。
对于C语言
来说,printf
这个函数就是一个用户操作接口
,并且它属于lib
,即库的范畴。在printf
内部,一定封装了真正的系统调用接口
,用户调用printf
函数,而在printf
函数内部再去调用系统调用接口
来访问屏幕这个硬件,进而在屏幕上输出。
为什么要再封装一层用户操作接口
呢?
用户操作接口
以更加简单的方式向用户提供了服务,比如printf
函数。用户无需学会复杂的系统调用接口
,只需要使用用户操作接口
就可以操控硬件。当然,有能力的人也可以直接调用系统操作接口
。用户操作接口
提供了跨平台能力,不论是Linux
还是Windows
等各种操作系统,都可以使用C语言
,C++
这样的语言来访问,但是这些操作系统的系统调用接口
很可能不一样,因此相同的printf
函数在Linux
和Windows
中封装了不同的系统调用接口
,从而使得一个用户操作接口
层面的接口,可以在各种在操作系统中使用,这就是用户操作接口
的跨平台能力。
当然,用户操作接口
还要shell
,指令
等等,比如说在Linux
中使用ls
指令,就会在屏幕上显示当前目录下的文件夹,这涉及一个向屏幕显示的操作,因此ls
指令内部应该也封装了系统调用接口
再往上就是用户
了,通过下层以操作系统为核心的软硬件体系架构,用户现在就可以方便快捷,又安全的形式来使用计算机。
至此,我就已经讲解完了计算机的软硬件体系大框架。
我再为大家回顾一下:
- 底层硬件:遵顼冯诺依曼体系结构,通过内存为枢纽的数据交换,实现了降本增效,使得计算机走入百姓家中
- 驱动程序 :操作系统管理硬件的重要手段,操作系统通过
驱动程序
获取硬件的信息,进而实行管理 - 操作系统 :计算机体系中的
管理者
,管理各种软硬件资源,遵循先描述,再组织
的重要思想,使得操作系统可以批量管理众多软硬件 - 系统调用接口 :为了保证操作系统提供的服务是安全可靠的,通过
系统调用接口
来帮助用户访问计算机,同时保护了操作系统内部的数据 - 用户操作接口 :直接通过
系统调用接口
访问计算机会比较麻烦,于是通过用户操作接口
以更加便捷的方式提供服务,并且提供了跨平台的特性,使得计算机的访问方便快捷