冯诺依曼体系结构
常见的计算机,如笔记本;不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。冯诺依曼体系结构如下所示:

计算机的本质:输入->计算->输出。截至目前,我们所认识的计算机,都是由一个个的硬件组件组成。常见的输入设备:键盘,鼠标,扫描仪,写板,网卡,磁盘等等;常见的输出设备:显示器,网卡,磁盘等等;中央处理器也称之为CPU,含有运算器和控制器,运算器主要处理算数运算和逻辑运算。在计算器中的输入输出设备,有些仅做输出设备,有些仅做输入设备,有些既是输出设备也是输入设备,我们将这些输入输出设备称之为外设(外围设备),外设是相对于存储器和中央处理器的说法。
冯诺依曼体系中的存储器 具体指的是什么?指的就是内存,内存即内部存储。我们听过的磁盘,u盘也有一个名称,就做外存,即外部存储。
学习冯诺依曼体系结构最主要的就是理解为什么要有内存。在回答这个问题之前,先来了解存储分级问题和体系结构效率问题。
存储分级问题
在计算机中具有存储功能的设备是非常多的。

这些具有存储功能的设备,距离CPU设备越近的,存储空间更小,速度更快,成本更高;距离CPU设备越远的,存储空间更大,速度更慢,成本更低。
体系结构效率的问题
既然计算机的本质就是输入->计算->输出,为什么中间还需要一个存储器?输入设备->CPU->输出设备,这种结构不是更好吗?输入设备和输出设备都是外设,而外设相较于CPU,它的速度特别慢 。CPU的处理处理速度是纳秒级别的,外设的处理速度是毫秒级别的。根据木桶原理:一个木桶最终能存储水的量,是由构成该木桶的最短的木桶片决定的,换句话说,如果计算机的结构为输入设备->CPU->输出设备,那么计算机的效率就完全取决于计算机的输入和输出设备了,这样的计算机效率太慢了。
既然速度慢,怎么解决这个问题呢?在设备与 CPU 之间引入新的设备 ------ 存储器。冯诺依曼体系结构规定,从输入设备输入的数据不能直接交给 CPU 处理,而是交给存储器,之后 CPU 需要读取数据只能从存储器获取数据,计算完的结果数据不能直接写入输出设备中,而是写入存储器中,再从存储器刷新到输出设备中。
在数据层面,CPU不与外设(输入设备和输出设备)直接交互,只会与内存交互。
但是引入新的设备之后,效率还是那样啊?依据木桶原理计算机的效率取决于外设呀?也就是说这套结构并没有使计算机的效率提升呀?逻辑确实如此,但是现在谈论的是纯硬件,在硬件之上还有操作系统。虽然从硬件上是这样的,但是可以提前将输入的数据载入到存储器,该操作被称为预加载 ,数据载入存储器之后,CPU读取数据只需从内存中去读,之后该系统在某个调度软件的调度之下,做预加载,就可以让整个系统的整体效率以内存为主。
数据可以提前加载,大部分情况下,处理数据时,就可以转换成CPU与内存的交互,计算机的效率就以内存为主了。再了解一个原理:局部性原理 ------ 当访问某位置的数据时,下一次访问有极大的概率访问之前访问的位置的周围位置的数据。正是因为有局部性原理,所以才可以将数据提前加载。
若想要造一台计算机,存储器全部使用寄存器,不是说距离CPU越近的存储设备,速度更快吗?存储器全部用寄存器,那速度还不飞起来?从技术上来看,这样做确实可以,但是从实际来看,这样会使计算机的造价成本大幅度提升,售价也会更贵,普通人无法消费;既然造价太高,那就减低造价,存储器全部使用磁盘,但是这样计算机就会很慢,效率很低,没有给使用者带来效率上的提升,对使用计算机的人来说没有作用。
若一个计算器的效率以内存为主,那么它的本质就是让普通人以较低的价格获取到效率一般的计算机,冯诺依曼体系结构为电脑提供性价比,使得电脑被人们广泛的接受,如此才能形成全球范围的网民数量,才可能孵化出互联网,这就是冯诺依曼体系的跨时代意义。
所以为什么要有内存?内存使电脑提速,且价格并未提高,使得电脑被人们广泛的接受,增加全球范围的网民数量,最终孵化出互联网。
在学习 C 语言时,曾听到过这么一句话:在编译C语言代码时,最终形成二进制可执行程序,可执行程序存储在磁盘上,而一个程序要运行就必须先加载到内存中。为什么程序运行之前要加载到内存中?
一个程序内部包含两个部分:一部分是逻辑,一部分是数据 ,但是最终的可执行程序全都以"数据"的形式体现出来,所以可执行程序就是数据。既然程序就是数据,根据冯诺依曼体系结构,输入数据之前需要预加载到内存中,即程序运行前需要预加载到内存中。所以为什么程序运行前要加载到内存中,因为这是计算机体系结构规定的。
输入和输出是站在谁的角度去考虑的?站在键盘(输入设备)的角度,将数据交给存储器,就是输出;站在显示器(输出设备)的角度,存储器的数据交给输出设备,就是输入,那么输入输出到底是以谁的角度去考虑的?我们口中的输入输出是以存储器 角度考虑的,而程序要运行需要先加载到内存里,也可以换种说法,以加载到内存中的程序的角度考虑的。
从外设读取数据到内存的过程称为 input,将内存的数据输出到外设的过程称为 output,称之为 IO。这也是为什么我们编写 C 语言/C++代码时,第一件事包含头文件写的都是 stdio.h 和 iostream,目的都是引入 IO 功能,这样就能使用 printf 和 scanf,cout 和 cin 函数了。
在了解存储分级时,提到距离CPU越近的设备,效率越高;距离CPU越远的设备,效率越低。从外设读取数据到内存的过程是 input,将内存的数据输出到外设的过程是 output,运算器与存储器之间的数据交互,这些都是计算机数据的流动。而计算机数据流动的过程本质就是拷贝 ,也就是说计算机的效率问题,由设备的拷贝效率决定 ,存储设备中所提到的效率是拷贝效率。
现在我在CSDN写了一篇博客,你可以看见我的博客。那么我写的博客在硬件层面上的流动过程是怎样的?假设浏览博客的设备使用的是电脑,那么博客就是在两个冯诺依曼结构之间流动的。

传送其它的文件也是相同原理。
在初学Linux的指令时,将 windows 系统上的文件直接拖拽到 Xshell 中,Xshell 中就出现了和 windows 一模一样的文件,windows 系统和 Linux 系统都是冯诺依曼体系结构,这一过程与上述分析的一模一样!需要注意的是:数据怎样流动与是什么软件无关。
操作系统
仅有计算机硬件而没有操作系统,就无法操作这些硬件。直接让使用者来操作硬件效率是很低的。无论是手机还是电脑,若没有安装操作系统,就如同板砖一般。任何一个计算机系统都包含一个基本的程序集合,称为操作系统(OS)。
操作系统有两层认知:广义上的操作系统和狭义上的操作系统。操作系统最核心的部分称之为内核,还需要给内核配上外壳程序,linux 系统配的就是 shell,windows 配的就是图形化界面,光有外壳程序还不够,还需要预装一些软件。
狭义上的操作系统:操作系统内核
广义上的操作系统:操作系统内核+操作系统外壳程序+操作系统配套的生态类的软件
之后提到的操作系统说的都是狭义上的操作系统,也就是操作系统内核
操作系统内核一般有四大功能:**驱动管理(与外设有关),内存管理(与内存有关),文件系统(与磁盘有关),进程管理,**任何一个计算机类的设备都需要这四大功能。
了解操作系统的基本知识后,可能会有一个疑问?为什么要有操作系统?用户没办法与硬件交互,所以就需要有一个东西能够将当前计算机中的各种设备管理好,所以就有了操作系统。

每一种硬件配一个驱动程序,没有驱动程序硬件是使用不了的,驱动程序是由硬件厂商提供的。
操作系统的核心功能就是将软硬件资源管理好,将软硬件资源管理好不是操作系统的意义,而是操作系统的手段,操作系统不是为了管理而管理。为什么发明操作系统 ?就是为了让人使用电脑更方便。通过操作系统将软硬件资源管理好,以此来给人提供一个良好的使用环境。(良好指:稳定的,高效的,安全的)。因此可以给操作系统下定义:操作系统是一款进行软硬件资源管理的软件。
了解到这自然而然会很好奇操作系统是怎么管理软硬件资源的?在回答这个问题前得先理解 OS 管理的本质。
例子:
在学校里,学生很多,而作为校方是需要将所有学生管理好的,教学安排,课程安排,班级安排,寝室安排等等。学校中管理层的角色很多,这里抽象化理解管理层只有校长。学校的管理层就抽象为:作为管理者的校长,作为被管理者的我(学生)。我在生活上,学习上出现了什么问题,校长是不会亲自处理这些问题,是另一名角色------导员,来处理学生的问题的。
我们做事情,无非两件事:做决策,做执行。今天我打算写一篇博客,这是做决策;我开始写,这是做执行。我要不要向这家公司投递简历,这是做决策;投递简历,这是做执行。管理者最核心的工作就是做决策,被管理者最核心的工作就是做执行。
在学校我们是很少与校长见面的,这也说明了管理者与被管理者两者不需要见面,管理者就能管理被管理者 !既然面都不见,管理者又是如何管理被管理者的呢?校长是如何知道我要毕业了,校长是如何知道我的毕业去向的?管理者获取到被管理者的数据就可以管理被管理者了 。管理被管理者,本质是对被管理者身上的相关数据做管理。然而管理者与被管理者没有见面,管理者又是如何获取到被管理者身上的数据的?通过导员,也就是驱动程序。校长决定评选奖学金,在学生信息中选出绩点和综测分高的学生,这说明了数据是提供决策依据的。
作为一名大学校长,学生众多,如何将被被管理者的信息管理起来?学生的基本信息有很多,姓名,学号,学院,专业,年级,班级等等,学生的基本信息也是学生的属性,能否将学生的信息让计算机去管理?定义一个结构体,结构体的成员变量就是被管理者的属性(姓名,学号,学院,专业,年级,班级,性别,民族,政治面貌等等),但是一个个学生的信息是孤立的,能否将 struct链接起来,在结构体中新增变量 ------ struct 指针,将所有学生的数据抽象成链表结构,使用数据结构将所有被管理者的数据统一管理,修改学生的信息抽象成获取指定结点的地址修改结点的属性,对学生信息的增删查改转化成对链表结构增删查改。
所以作为大学的校长管理学生的信息,先将所有学生的信息使用结构体描述起来,再将所有学生的信息作为结点一个个组织起来。先描述一个事物,再以各种数据结构组织起来,就可以管理了 。将校长换成操作系统,将学生换成软硬件资源,操作系统如何管理软硬件资源?回答:先使用结构体描述,再使用各种数据结构组织 。操作系统是一款软件,绝大部分操作系统是用 C 语言写的,如果操作系统要管理软硬件,首先定义一个 struct 结构体,成员变量为软硬件资源信息,再使用数据结构链表将这些结点组织起来。因此我们可以推断:OS内部核心的东西是数据结构!!
为什么 C++ 语言中要有类和 STL?为什么 C++ 语言是面向对象的语言?因为我们使用 C 语言/C++解决问题,就是对各种信息做管理,而 C++ 中的类对应的就是先描述,STL对应的就是再组织,这也是为什么我们在学习 C++ 时,都是先实现类,再根据具体问题使用特定的 STL 容器。Java 和 python 等面向对象语言也有类似于 C++ 中类和 STL 的结构,这说明了先描述,再组织是语言的特点。先描述,再组织是现实问题进行计算机建模的核心规律。
软硬件体系结构

整个计算机的软硬件是一个层状结构,底层硬件整体是以冯诺依曼体系结构组成的。
操作系统可以对各种资源进行管理,但是操作系统不能只是将这些资源管理好就可以了,还需要提供给操作者稳定的,安全的,高效的使用环境。操作系统内一定存在大量的数据结构来管理各种属性信息,如果操作系统允许用户直接访问它的各种代码数据,这个过程是特别不安全的,也就是说操作系统是不允许用户直接访问它所管理的操作系统的,既然如此操作系统又是如何为用户提供良好的使用环境的呢?
例子:下图是一个简化的银行结构:

现在有一名顾客要到银行存钱,让顾客直接去金库和银行电脑进行存钱操作,这样做可以吗?当然不可以。银行需要保证自己的安全,因为顾客中可能有坏人,为了保证自己的安全,银行整个系统会将所有的顾客都当成坏人!这下就出现问题了,银行既需要为顾客提供服务,又将所有顾客认为是坏人,此时银行需要考虑如何在保证自身安全的前提下,为顾客提供服务。银行可以在自己的系统内开放窗口,顾客到银行存取钱,不能直接进入银行后部,通过银行开放的窗口,与工作人员进行沟通,让工作人员帮助顾客存取钱。
操作系统也是如此,操作系统可以提供一层软件层,也就是系统调用,系统调用 相当于操作系统为用户开放的"窗口",这些"窗口"本质上是一个个系统提供的函数接口 。我们之前的学习中见过系统调用吗?当然见过。操作系统的调用是操作系统提供的,所以调用起来会有成本,必须了解操作系统才能调用操作系统的函数!我们编写 C/C++ 代码引用的库就是系统调用,我们调用的很多 C/C++ 函数都是对系统调用的封装。
比如调用的 printf 函数,printf 函数的本质是向显示器硬件写入数据,我们使用 C 语言向显示器硬件写入 "hello linux" 时,是使用 C 语言直接向硬件写入的吗?操作系统是软硬件资源的管理者,所以访问硬件必须要经过操作系统。所以使用 printf 函数向显示器硬件中写入的本质,就是 printf 函数系统调用,通过操作系统贯穿显示器驱动,再向显示器内部写入数据。所以凡是涉及访问硬件的操作,都需要经过操作系统,调用系统调用!
用户使用操作系统的行为:使用操作系统;在操作系统上做开发操作;在操作系统上做管理操作。为了满足用户的使用操作系统的不同场景,操作系统会提供对应的功能。如果要做开发操作,操作系统提供一个库;如果要使用操作系统,操作系统提供一个图像化界面/外壳程序;如果要管理操作系统,如安装/卸载软件,操作系统提供安装/卸载等指令。
系统调用是否是外壳?不是。外壳程序是C语言开发出来的,使用的是 C 语言标准库/系统调用设计的一款软件,它的本质就是命令。指令是否是系统调用?不是,指令的本质是文件,是使用C语言编写的可执行程序,指令的底层使用的也是系统调用。无论是外壳程序,库,还是指令,它们都是直接或间接的调用系统调用来完成自己的工作的,但是它们三个是不一样的。