冯诺依曼体系结构与操作系统
文章目录
- 1. 冯诺依曼体系结构
- 2. 数据流的传输过程
- 3. 操作系统的基本概念
- 4. 设计操作系统的目的
- 5. 如何理解管理
- 6. 系统调用和库函数概念
1. 冯诺依曼体系结构
约翰・冯・诺依曼是 20 世纪最重要的数学家之一,在多个科学领域都有着深远影响。
冯・诺依曼体系结构也被称为普林斯顿结构,是一种计算机的经典设计架构。它将计算机的硬件系统划分为五大基本部件,分别是运算器、控制器、存储器、输入设备和输出设备。
其核心特点是采用存储程序原理,也就是程序和数据以二进制的形式一同存放在存储器中,计算机按照顺序依次从存储器中取出指令并执行,指令执行过程中可以对数据进行相应的运算处理等操作。
我们所认识的计算机,都是有一个个的硬件组件组成:
- 输入单元:包括键盘,鼠标,扫描仪,写板等。
- 中央处理器(CPU):含有运算器和控制器等。
- 输出单元:显示器,打印机等。
关于冯诺依曼,必须强调几点:
- 这里的存储器指的是内存。
- 不考虑缓存情况,这里的 CPU 只能对内存进行读写,不能访问外设(输入或输出设备)。
- 外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
总结:
- CPU 不和外设直接打交道,而是和内存直接打交道。
- 所有的外设,如果有数据需要载入,那么只能载入到内存中;而如果从内存中写出,那么一定是写入到外设中。
我们知道,程序要运行必须先加载到内存,那么为什么呢?
因为 CPU 要执行我的代码、访问我的数据只能从内存中读,这是体系结构规定好的。
那么体系结构为什么这么规定呢?本质就是要提高计算效率。
所以通过输入设备数据只能到内存,然后计算机计算完以后,读数据从内存里读,读完之后写到内存里,然后再把数据刷新到外设里,最后对应的外设(显示器)就显示出来了。
2. 数据流的传输过程
实例 1
假设小A在成都,小B在北京,他们进行QQ聊天。小A从键盘输入向小B发了一个 “你好”,这个 “你好” 叫做数据流,那么在不考虑网络的情况下,这个数据流是如何在不同的电脑中流动的?
我们可以把小A和小B的电脑都看作是一台冯诺依曼结构的电脑,这里的输入设备对小A来讲就是键盘,小A一旦摁键盘了,他的数据其实是先输进了内存中,然后小A经过网络发送的 “你好”,先要CPU去计算,假设为了数据安全聊天消息是经过加密的,所以要执行对应的加密算法,把 “你好” 加密之后写到内存中,之后再定期的把数据刷新到输出设备,这里的输出设备,也就是网卡。
小A给小B发消息的时候,小A的显示器上也能看到给小B的消息。所以就相当于把这个数据,一式刷新两份儿,给网卡一份儿,给小A的显示器也一份儿,所以小A也就看到了。
那么,接下来网卡把数据发送经过网络,再对应到小B的计算机里,那么小B的计算机里面拿到数据的时候,一定是网卡这个设备先读到了数据。当网卡拿到数据,它一定把读到的数据拿到小B电脑的内存当中。因为数据是经过加密的,那么所以最终这个数据再经过CPU内部解密,再写到内存里,变成 “你好”,然后再刷新到小B的输出设备,也就是他的显示器上。
所以不考虑软件,它的数据流是这样走的;考虑软件,它也必须是这么走的。
因为软件是依托于硬件的,软件再怎么写,也必须得遵守这里的数据流程。
这是硬件体系结构给我们带来的认知。
实例 2
假设现在小A要通过QQ给小B发送文件呢,小A经过这种拖拉的方式,把文件拖拉到我们对应的QQ的对话框里面,然后一点击回车,小B就收到了,那是怎么做到的呢?
文件里面不就也是数据吗?和这个 “你好” 有什么区别呢?无非就数据量大了点儿。
所以呢,在没有发文件时,小A的数据在磁盘里,所以一定是把数据从磁盘里面搬到内存中。说白了,就读到QQ里。QQ在加密之后,把加密好的数据再写到内存里,然后刷新到网卡里,网卡就会传送给小B。
小B的主机拿到了之后,把数据读到内存里,再解密,然后再写到内存,刷新到小B的磁盘上。所以你会发现,其实这个时候就变成了数据从磁盘到磁盘。
但万变不离其宗,只要我们把体系结构理解通了,所有的软件的现象,我们就有一个硬件角度去解释了。
3. 操作系统的基本概念
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。
笼统的理解,操作系统包括:
- 内核(进程管理,内存管理,文件管理,驱动管理)
- 其他程序(例如函数库,shell 程序等等)
4. 设计操作系统的目的
- 与硬件交互,管理所有的软硬件资源。
- 为用户程序(应用程序)提供一个良好的执行环境。
所以,操作系统就是进行软硬件资源管理的软件,它对下要管理好软硬件资源,它对上要提供一个良好的、稳定的、高效的,安全的运行环境;
5. 如何理解管理
在整个计算机软硬件架构中,操作系统的定位是:一款纯正的 “搞管理” 的软件。那么操作系统怎么做到的?也就是怎么去管理的呢?
可以举个例子:校长是管理者,而学生是被管理者,我们除了开学典礼之外,就很少见到校长,那么校长又如何进行管理的呢?
我们知道管理者是不需要和被管理者直接交互的,依旧能够把被管理对象给管理起来,管理者正的界定是要有对重大事情做决策的。并且管理者对重大事宜有决策的权力。
虽然我作为被管理者,不直接和校长打交道。但是我的所有数据(学号、姓名、年龄、地址、籍贯等等)早已经被校方拿走了,而且一直在更新,那么本质不是对人进行管理,而是对数据进行管理。
换言之,比如说我进入公司里了,公司的CEO连我面都没见过,可是我什么时候入职的?近半年有什么重大贡献?我贡献了多少行代码?贡献了多少个bug?为公司解决了多少问题?这些都叫做数据,只要把我的方方面面的数据全部拿到给公司的CEO,那么他都不需要和我见面,照样可以把我管理起来。
所以最终结论叫做:管理的本质是对数据。
我们知道,校长是做决策的,而辅导员是拿到数据并且执行决策的,学生就是被管理的。
操作系统是一个管理软件,那么被管理的角色是谁呢?这里的角色就是硬件啊。所以,操作系统是对硬件做管理的,并且它不需要和硬件直接打交道,只需要对硬件的数据做管理就可以了。
那么其中操作系统和硬件都不直接打交道,怎么拿到硬件的数据呢?所以在操作系统和硬件之间,还有一种软件层,这层软件层叫做驱动。
那么一旦底层硬件来了,它的硬件数据便在操作系统的受益之下。将数据拿到操作系统内部。当操作系统根据数据做决策的时候,也由对应的驱动程序去执行。
现在我们已经知道了:校长通过对数据做管理,来对 被管理者 进行管理,数据的采集和决策的执行由我们的辅导员来做的。
假设学校有两万人的时候,其中辅导员儿可能有十几个,学院也有几十个专业。那么有这么多的辅导员儿,对应的就是有这么多的驱动程序,操作系统内会存在大量的数据。
作为校长来讲,他用Excel表格维护了几十张这样的表,每一条对应的就是一个学生的信息。所以校长每天的工作就是从头到尾一个个去对比这些表格的数据,一年下来校长身体不坏,掉眼睛也废掉了啊,天天盯着这些数据看。
所以数据量大的时候一定会带来数据本身的管理负担,怎么样对数据做更好的管理呢?
虽然校长所要管理的学生信息多,但是种类都是一样的,还不是学号、姓名、年龄、地址等等。那么可以定义一个 struct 结构体,里面包含了这些学生的所有信息。
用结构体来那么定义各种学生对象或者变量,将学生属性填充起来,最后对于学生的管理变成了对这一个一个变量的管理。
但是光把学生们的信息描绘起来还不行,校长他又在自己维护学生的这个结构体里添加了一个 struct *next
。
相当于来了一名学生,我就把学生的信息填好,构建成一个链表,然后用我们的头结点指向新加入的节点。哪怕学生越来越多,无非就是向链表当中不断的新创建节点,然后把学生的属性信息填到节点里,然后链到我的链表里。
此时,校长对学生数据做管理,就变成了对链表进行管理。
假设,我想找一下学校里学习成绩最好的人,给他去评我们学校的奖学金。那么,以前我的做法就是在 excel 表里不断去遍历,拿着所有同学的学习成绩,在这里一个个去找。
现在就不用这么费劲儿了,只需要设计一套遍历链表的算法,根据学生的这个 score 得分作为对应的一个 key
值,把所有的链表当中 score 最大的那个节点找到,那么此时这个学生信息就拿到了,所以这个学生就可以评奖学金了。
如果学校里新入学的一名学生报到,那么学生入学之后,辅导员知道了,辅导员把信息告诉校长,校长就直接调用 insert
方法,把节点插入进去,这个学生就被管理起来了。
那么有一天这个学生,做一件特别糟糕的事情,被勒令退学了,辅导员把这名学生信息交给校长,校长执行链表的 delete
操作,从对应的链表当中找到这个学生结点,把这个结点去掉,那么此时这个信息就在学校当中被清理掉了。
总之,就是把要 被管理的对象 转化成 对链表做管理。
但是必须得做两个重要的阶段:
- 第一个阶段叫做:先描述(面向对象)。
- 所谓的先描述,说白了就是把你要管的被管理对象怎么抽象出来,变成一个我们对应的结构体。
- 第二个阶段叫做:再组织(数据结构)。
- 所谓的再组织,就是将所有的,根据该结构定义出来的一个一个的对象。将它设计成特定的数据结构,转化成对被管理对象的管理,变成了对某种数据结构的管理。
那么所有管理的本质逻辑都是这六个字:先描述再组织。
总结:
- 管理的本质:对数据做管理。
- 管理的方法:先描述,再组织。
6. 系统调用和库函数概念
我们去银行办理业务的时候,会看到有一道厚厚的玻璃墙,然后上面开个小洞,你要办业务的时候,坐在银行的那个柜台口,然后工作人员让你通过一个小洞口把资料递进去,比如你要取钱,工作人员就会把钱从窗口给你扔出来。
为什么要这样做呢?严格意义上来讲,银行系统不相信任何人,所以银行要将自己保护起来。所以银行就在玻璃墙上开了一个小窗户,你办理什么业务,只需要通过这个窗户就可以了。此时,银行就既保护了自己,又对外提供了服务。
同样的,操作系统相不相信任何人,但是也必须给上层用户提供各种服务,在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分
由操作系统提供的接口,叫做系统调用。
所以通过 系统调用接口 操作系统既把自己保护起来了,又对外能够向上提供各种服务,
这里的系统调用就是 C 语言式的接口,也就是操作系统通过 C 语言给我们提供的函数调用。以后你想访问任何硬件,必须得通过操作系统,而且一定有操作系统的接口可以访问。
就比如你现在用 C++ 写的代码全部那么写好之后,然后有需要再去调 C++ 的库来完成你的功能,你的程序跑起来,其实就是在系统调用接口之上再进行调用,然后再在操作系统内部做的。所以你的所有的行为其实最终都是通过系统调用接口来做的。
系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
如下图所示:
最底层的我们叫做硬件,冯诺依曼形式组织的驱动程序帮我们去控制各种硬件,操作系统经过先描述再组织,对硬件资源做管理,它把下面资源管理好,目的是给上面提供更好的服务。同时,它还要对上提供各种接口操作,方便上层来对硬件做操作,所以怎么提供呢?那就是经过系统调用接口层。