目录
体系结构
目前,市面上大部分计算机都遵循冯诺依曼体系结构。
组件划分
冯诺依曼体系结构组件分为
1、输入设备:比如键盘、鼠标、磁盘等。
2、输出设备:比如网卡、显卡、磁盘等。
3、存储器:内存
4、运算器:主要完成算术运算和逻辑运算
5、控制器:主要协调计算机内部设备之间的信息流动。
其中,运算器和控制器为中央处理器(CPU)中的组件。
这些设备都是独立的。
有些设备只做输入(读方法)、有些设备只做输出(写方法)。
有些设备即做输入还做输出(磁盘).。
冯诺依曼体系结构图
上图红色箭头是数据信号流动,黑色箭头是控制信号,我们先只了解数据信号流动。
不同设备是之间物理连接的,是由总线集成到主板上面的。
通过不同设备之间的连接的手段,来达到设备之间的信息/数据流动的目的。
设备之间的信息流动的本质是设备之间不断进行数据的来回拷贝的工作。所以,拷贝的整体速度是决定计算机效率的重要指标。
为什么要引入内存?
既然数据的流动就是在不同设备之间来回拷贝,那么为什么不直接将数据从输入设备拷贝到CPU,然后由CPU处理完之后,再拷贝回输出设备呢?为什么还要有内存的存在呢???
为什么体系结构不设计成这样呢?这样还减少了两次拷贝,还不用内存,岂不美哉。
具体原因如下:
计算机存储体系金字塔
由上到下,价格逐渐降低、容量逐渐增大、设备整体速度(效率)逐渐下降。
由于CPU的效率高,输入、输出设备效率很低。由于木桶原理,所以导致计算机整体的效率取决于输入、输出设备,而这俩的效率很低,所以就导致CPU很快就处理完了,但是输入、输出设备拷贝工作还没完成,效率上面大打折扣,所以这种体系结构的计算机效率很低。
这个时候,就需要一个介于输入、输出设备和CPU效率之间的设备-------内存
内存可以看作是一个非常大的缓存,介于输入、输出设备和CPU效率之间,且内存相对比较便宜。
内存预加载和缓存机制
引入了内存之后,计算机整体效率就取决于内存了。---------但由于木桶原理,计算机效率还应该是取决于输入输出设备呀,为啥就取决于内存了???
原因如下:
引入内存之后,由于考虑到数据流动一定会多拷贝两次数据,我们无法改变需要多拷贝的事实,但是我们可以改变拷贝的时机,尽量让内存拷贝的工作便捷于计算机。
我们可以在CPU处理别的工作的时候,将下一个数据预先加载(拷贝)到内存中,然后计算机从再内存中获取拷贝数据进行处理,处理完之后将结果拷贝给内存缓存下来,然后CPU可以继续执行接下来的任务,而内存在计算机资源不紧张时,再将刚刚处理好的结果拷贝给输出设备。
但是我们如何保证数据会在合适的时机将自己的资源数据拷贝给内存呢?我们如何保证内存会在合适的时机去把处理好的资源数据拷贝回给输出设备呢?
这个控制就需要操作系统去完成了。操作系统的好坏决定了预加载和之后刷新的时机,决定了计算机效率的高低。
冯诺依曼引入内存,把效率问题转化为了软件问题。
所以,计算机的效率就以内存效率为主了。
冯诺依曼体系数据流动的整个过程
举个例子
程序在运行的时候,必须先把程序预先加载到内存。
就是因为刚开始文件是在磁盘(输入设备)上面的,将文件加载到内存上去,然后再被CPU拷贝下来执行处理,再拷贝回内存,再由内存给输出设备。
在数据层面上,CPU只和内存交互,输入、输出设备之和内存交互。
计算机上的所有让CPU处理的操作都必须按照冯诺依曼体系结构的规定来执行。
操作系统
计算机开机,第一个被加载的软件就是操作系统。
操作系统是一个进行软硬件资源管理的软件。
操作系统要以管理好软硬件资源为手段,完成给用户提供良好的服务的目的。
计算机层状结构
当然,底层硬件是根据冯诺依曼体系结构相互连接的。
操作系统的职责
1、管理好软硬件资源(手段)
2、给用户提供良好的服务(目的)
如何管理好软硬件资源
操作系统管理软硬件资源,归根到底是管理软硬件资源的数据,根据数据对不同的资源做出不同的决策。
操作系统要想管理好软硬件资源,就首先要将这些软硬件资源的属性封装到类(先描述),再借助合适的数据结构将这些资源实例化的对象管理起来(再组织)。
操作系统管理软硬件资源就是"先描述,再组织"的过程。
如何给用户提供良好服务
系统调用接口
系统调用接口就是由C语言设计的函数,由操作系统提供。
用户只能通过操作系统提供的系统调用接口来让操作系统帮助自己实现某种功能。
用户不能绕过操作系统去访问底层的软硬件资源,让底层软硬件资源去为用户做事情。
操作系统不允许用户绕行访问,也不允许用户直接访问操作系统内部,所以操作系统将自己的部分功能封装成接口,提供给用户使用,这些接口就是系统调用接口。
用户操作接口
有些用户不会使用操作系统提供的系统调用接口,为了使操作系统的服务效率更加高效,操作系统又提供了用户操作接口。
用户操作接口大部分都是封装的系统调用接口。
比如一个C/C++程序,我调用了一个printf/std::cout函数,最终运行出来是在显示器文件上面打印,在显示器文件上打印就需要借助操作系统所提供的系统调用接口。所以,类似于printf/std::cout函数就必须在它的内部实现对系统调用接口的封装。
所以,如果用户会使用系统调用接口,那就可以直接使用系统调用接口。如果不会,就使用用户操作接口,用户操作接口底层会去调用系统操作接口。
对可移植性、跨平台性的理解
这里用lib标准库中的函数进行举例。
在程序设计的时候,lib标准库实现了对不同平台的封装,内部调用也使用对应平台的接口。在用户体验下来,只需要调用同一个接口就行了,内部会去调用对应系统平台的接口。
浅看一下