前言:本文从软硬件角度计算机解释软硬件结构
硬件—冯诺依曼体系结构
软件—操作系统
什么可以称为计算机呢?
计算机应该满足的功能:
人类历史上第一台计算机由约翰·冯·诺依曼(后面称为冯·诺伊曼)创造,冯·诺依曼提出了计算机制造的三个基本原则
冯殿诺依曼体系结构在硬件上规定了计算机底层结构离不开输入设备,输出设备,存储器,中央处理器.
输入设备:键盘,磁盘,话筒等
输出设备:显示器,磁盘,扬声器等
存储器:特指内存,掉电易失,数据处理快
中央处理器(后面用CPU表示中央处理器):运算器+控制器
为什么从输入设备获取的数据不能直接交给CPU处理,处理完的数据不能直接传输给输出设备,必须经过中间存储器呢?
计算机的不同存储空间有着不同的存储效率和访问效率
存储金字塔:离CPU越近的存储器访问速度越快,单体容量小,成本高
离CPU越远的存储器访问速度越慢,单体容量大,成本低如果输入输出设备直接和存储器进行数据传输,因为输入输出设备离CPU远,所以对数据处理速度低,但是CPU对数据的处理是非常快的,根据木桶原则,整个计算机处理数据的速度取决于效率低的输入输出设备,而不是CPU,同时更容易时CPU处于闲置状态.
相反,如果让内存和输入输出设备交互,CPU只负责对内存中的数据进行处理并把数据返还给CPU,而内存堆数据处理速度远大于硬盘等输入输出设备,所以这样可以减少因木桶原理而减少的效率.
经过输入输出设备的数据通过存储器传是否可以加快计算机处理数据的速度呢?
在CPU和输出输出设备间插入存储器,细心的朋友可以发现,在CPU-内存-输入输出三种设备中,对数据处理最慢的还是输入输出设备,木桶原则应该还存在,计算机整体效率仍然取决于输入输出设备,既然这样,引入内存不是多此一举吗?
我们可以通过预先加载和缓存技术解决上述问题:
**预先加载:**在CPU执行上一次指令时,提前将输入设备中的数据加载到内存里,当CPU执行完上次指令后,可以直接从内存中读取数据执行指令.
**缓存:**CPU将处理完的数据写入到内存中,等计算机处于闲置状态时,再将内存中历史上保存的数据刷新到输出设备.
通过预先加载和缓存技术可以让CPU只和内存交互,使计算机的效率取决于内存效率,提高计算机效率.ps:预先加载和缓存的工作由操作系统来完成,因此我们可以将硬件上的问题转化为软件上的问题(操作系统).
冯·诺依曼结构中引入内存的意义
数据层面:通过将计算机效率取决于硬件拷贝数据的速度这种硬件层面的问题转换为操作系统预先加载和缓存这种软件层面的问题,进而提高计算机效率
经济层面:内存的成本较为适中,所以在尽量不使用过高的成本提高计算机的效率.
只有成本低了用的人才会多,互联网才会普及
解释:运行程序首先要将程序加载到内存中
根据冯·诺伊曼结构,CPU只能从内存中读取数据,而可执行程序的指令需由CPU来执行,因此必须将可执行程序从磁盘加载到内存中才能交给CPU执行
请解释当我通过互联网像被人发送“在吗”时数据的流动
总结:
冯·诺伊曼体系结构通过引入存储器让我们可以使用较低成本提高计算机的运行效率.
冯·诺伊曼体系结构将计算机效率取决于硬件转化为软件(操作系统)
数据传输时,外设和内存交互,内存和CPU交互.
什么是操作系统?
操作系统(后面称为OS)是一款对下层软硬件进行管理(手段),对上层用户提高稳定,安全,高效的运行环境(目的)的软件.
上面我们说过,程序运行时首先需要被加载到内存,而操作系统是一款软件,想要运行它也必须加载到内存中,而操作系统是用来对软件进行管理的,所以一定要先于所有软件加载到内存中.
所以操作系统是第一个被加载到内存的软件.
Linux是一款操作系统,Linux操作系统主要由以下两部分组成
- Linux内核(kernal):是操作系统的核心,主要负责内存管理,进程管理,文件管理,驱动管理
- 系统工具:用于管理系统和执行各种任务的软件,Shell(命令行解释器),文件管理器,编辑器,编译器等
操作系统负责对软硬件进行管理,那么什么是管理呢?
在这之前,我们需要知道软硬件层次结构
管理者直接和被管理者不一定直接进行交互
举个例子:你是一名学生,你们所做的工作全是由校长所规定的,但是你有经常和校长见面吗?并没有,校长只需要吩咐事项(做决策),剩下的交给辅导员(假设只有你 辅导员 校长三方)来监督你们完成,所以管理者和被管理者不一定需要直接交互.
管理的本质是对数据进行管理
在你刚刚进入大学时,甚至连同学的名字都不知道,此时你已经被划分好在哪一个班,哪一个寝室了,你已经“被管理”起来了,但是管理者并没有见到你,只是投档时你的高中已经把你对应的档案袋交给了大学,校长已经拿到了你的档案袋,档案袋里面有你的各种信息,通过这些信息校长就可以将你分班,分寝…
所以管理不需要知道你是谁,只需要拿到你所对应的数据.
上面说过,管理者不会直接和被管理者进行交互,那么管理者如何拿到被管理者的数据呢?
实际上管理者会通过执行者拿到数据,让执行者去和被管理者交互,例如辅导员就是一个执行者,辅导员通过和你交互得到你的绩点,综测排名…再上交给校长,校长通过这些数据对你的数据决定你是否可以评优评先…操作系统相当于管理者(校长):负责管理软(程序)硬(设备)件
驱动程序相当于执行者(辅导员):驱动程序负责将与之对应的硬件操作打包,对操作系统提供操作硬件的接口
底层硬件相当于学生(被管理者)
管理的方式—先描述,再组织
当被管理者数量很大时,管理者所需要面对的数据量是非常大的,如何管理大量的数据呢?
可以通过**“先描述,再组织”**的方式管理数据,先将学生对应的数据用一个结构(struct)表示,在通过某一种组织方式(顺序表,链表等数据结构)将多个结构组织起来形成一个学生信息管理系统,此时对学生的管理(增删查改)转化为对数据结构的管理(增删查改)回到操作系统:操作系统通过先描述,后组织的方式管理硬件.
假设操作系统以链表的方式组织数据
**描述:**Linux内核是C语言编写的,因此使用C语言的
struct
描述被管理者struct device { char name[];//硬件名称 int states;//硬件当前的状态 ... //设备其他的属性 struct device* next;//保存写一个设备的地址 }
组织:
以后当某一个设备出现故障,操作系统直接将链表中的该设备信息删除,也就是对链表的删除.
注意:先描述-再组织的管理方式会贯穿整个Linux学习周期,凡是涉及管理方式,均为“先描述-再组织.”
总结:操作系统对硬件管理的本质是对硬件所对应的数据进行管理,管的的方式是先描述-再组织
聊点别的:
数据结构这门学科本质上就是告诉我们将不同类型的数据如何组织起来更高效,C++STL库也提供了组织数据的方式,其实只要是面向对象语言,都应该提供类似STL的库,因为面向对象本质是描述数据,但是光有描述不足以管理数据,还需要通过一些方式将描述的数据组织起来,这样才可以通过这门语言更高的管理数据.
如果没有操作系统,那么我们需要自己手动控制硬件(一只手打王者荣耀,一只手操控电路板(~真是一场酣畅淋漓的体验啊~).
操作系统的作用是
那么操作系统是如何提供稳定,安全,高效的运行环境呢?
操作系统只对用户提供特定的
system call
(系统调用接口)保证用户不会直接访问操作系统,用户只能通过system call
执行系统层面的操作,例如像显示器输出字符串,因为system call
涉及了系统层面的知识,所以有些用户使用起来有困难,若对外提供的用户操作接口封装了系统调用,那么用户只需要会使用用户操作接口即可完成系统层面的操作,例如C语言中的库函数pirntf
就是一个用户操作接口,其中封装的system call
可以像显示器打印字符串.
为了不让操作系统中的所有数据暴露给用户,操作系统只对用户提供system call
使用户完成需要的操作
**系统调用在保证操作系统安全的情况下向用户程序提供了对底层硬件访问和执行系统级别任务的方法.**例如你需要去银行取钱,若不考虑使用取款机,会有一个银行窗口将你“挡在外面”,你只能通过银行窗口取钱,对于操作系统来讲,
system call
就相当于一个银行窗口防止你直接访问操作系统.
因为Linux是用C语言写的,因此Linux的
system call
是使用C语言写函数的
既然用户必须通过system call
才能访问操作系统,那么用户是否可以绕过操作系统直接访问硬件呢?
不可以,下面是不可以的原因
- 硬件复杂性:现代计算机系统的硬件通常非常复杂,直接访问硬件需要深入了解硬件体系结构和寄存器级别的编程
- 安全性:用户直接访问硬件可能导致系统容易受到恶意攻击,操作系统通过权限管理和隔离确保不同的应用程序只能访问其授权的数据
- 稳定性:操作系统负责处理硬件抽象和资源管理,以确保多个应用程序可以在同一台计算机上共存而不相互干扰。如果用户直接访问硬件,可能会导致资源冲突、竞争条件和系统崩溃。
注意:在嵌入式设备中可能可以直接对硬件进行操作
总结:任何人都不能直接访问操作系统,必须通过system call
才能访问.
我们都知道printf
是像显示器打印字符串,也就是说printf
函数需要访问硬件,之前说过,用户程序想要访问硬件必须通过操作系统,而对操作系统的访问又离不开system call
,所以printf
函数底层一定是封装了可以让操作系统访问显示器的system call
,同理,sacnf
内会封装可以让操作系统读取键盘输入的system call
.
既然printf
和scanf
中封装了对应的system call
,我为什么不直接调用system call
像显示器打印/键盘读取,而是要绕一层调用printf
和scanf
呢?
接着银行的例子,银行提供对应的窗口后,是不是所有人都会熟悉办理流程呢?当然不是~只有具备一定理解能力的人才能够顺利的办理业务,银行当然也知道这一点,因此他们又设立了一个服务层,不会使用银行窗口的人可以在服务层寻求帮助,通过服务层,不管你识不识字,你最后都可以取到钱.
system call
是系统级别的接口,也就是说需要对操作系统有一定了解的人才会使用,而大多数用户并不了解操作系统,因此像用户提供类似于printf
和scanf
级别的库函数,同样可以使用户完成对硬件资源的使用.
C标准库(libc)具有跨平台性的原因之一是因为C的库函数中调用的
system call
是由当前操作系统所决定的.例如Windows下printf
函数封装的system call
是代码A,Linux下printf
函数封装的system call
是代码B,但是C的库函数printf
实现时并没有指定是使用代码A还是代码B,具体情况取决于当前操作系统,如果是Windows则使用代码A,如果是Linux则使用代码B
库函数是用户操作接口的一种,库函数可以调用system call
用户操作接口还有:
有了上述知识,我们就将计算体系结构搭建起来了
一方面,操作系统通过“先描述,再组织”的方式对软硬件资源进行管理,保证底层硬件及驱动程序是被有序的组织起来,另一方面,为了降低用户使用成本,操作系统通过一系列的系统调用,用户操作接口对用户提供一个稳定,安全,高效的运行环境.