体系结构有一种是从计算机组成的角度去谈的,还有一种是从芯片架构方面去谈的,下面我们是从我们的计算机组成原理的角度去理解冯诺依曼体系结构的。
我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。
计算机里面的几乎所有的设备都有数据存储的能力!
磁盘外设是永久存储介质。
CPU这个设备,它处理数据的速度是非常快的,然后是内存,然后是各种外设(这里我们以磁盘为代表)。
以CPU为中心,距离CPU越近,存储效率越高,造价越贵。
那么为什么要进行存储分级呢?
有人说,为什么不直接全部使用高价格,制作出存储效率最高的计算机出来呢?
原因:如果全部用高价格的存储介质,那么必定带来的就是造价成本太贵了,普通老百姓用不起。
那又有人说,为什么不全部使用最低价格的存储介质呢?这样就能解决造价太贵的问题了呀!
原因:如果我们全部用便宜的存储介质,计算机价格便宜,但是由于存储效率太低,基本上用不了。
所以出现了存储分级,使得造出来的计算机成本不太高,效率也不差,自然计算机的价格也不太贵,那么当代的计算机,老百姓们也用的起了,这才得以广泛使用。
与其说是存储分级,不如说是速度分级,或者说是存储分级。
在数据层面上 ,当代的CPU一般是不和外设直接打交道的。 为什么呢?
原因:根据木桶效应,装多少水取决于那块最短的板,也就是说,在数据层面上如果CPU直接和外设打交道,那么计算机的性能最终取决于外设的存储效率,而又因为外设的存储效率太低了,所以会拉低整个计算机的性能。所以在数据层面上,CPU应该优先要和内存打交道,因为内存的存储效率是要比外设高的,如果CPU直接和内存直接打交道,那么根据木桶效应,整个计算机的性能是由内存决定的,这样就使得整个计算机的性能相对于CPU与外设直接打交道的性能要高很多。
内存就是一个硬件级别比较大的缓存。
所以,基于冯诺依曼体系结构的计算机,他的本质:用比较少的成本,做出了效率不错的计算机,也就是说性价比比较高。
对冯诺依曼的理解,不能停留在概念上,要深入到对软件数据流理解上
下面我们分析三个案例:
1.先拿我们平常写C语言代码的案例来说,我们应该都听过说:程序在运行之前,都要先把程序加载到内存,为什么呢?
程序=代码+数据,最终都需要CPU来进行处理,而CPU需要先读取到你所写的这些代码和数据,但是CPU只和内存有数据层面(可以理解为二进制层面)的交互,最终形成了一个.exe,本质就是一个文件,只能在磁盘(外设)中保存,所以程序想要运行就得把.exe文件加载到内存才能让CPU来跑。
2.假设今天我在北京,你在西安,我们都登上了qq这个软件,我们都打开了各自的对话框,发了一个“在吗?”。请在硬件层面上解释一下“在吗?”这个信息在设备上的数据流动。
首先,在我的电脑上输入设备肯定是键盘,由于我发过去的信息给你的时候我们通常在QQ对话框上看到的不仅仅是“在吗?”这条消息,还有发消息的时间等等内容,学过网络的小伙伴呢肯定都知道,我们是要将这条消息进行打包封装的,但是我们这里就暂且忽略网络,我们的QQ运行的时候就是被加载到了内存的,所以我们在QQ发送的消息也可以理解为从键盘输入加载到了内存,然后经过CPU处理比如打包封装,通过我们的网卡外设进行输出,然后经过网络传输,传输到你的输入设备同样是网卡,然后加载到内存,通过解析,去除封装把消息输出到你的显示器上,那么你就能看到我发过去的“在吗?”这条消息,那么有时候我们发送的消息有时候自己也能看到自己的消息呢是因为,我们的输出设备不止一个,我们通过网卡的输出发送数据的同时,也可以输出一份数据到显示器当中让我们自己能够看到。
3.那么如果我把文件拖拽到了QQ的对话框,发送文件给你,请描述一下这个过程?
首先呢,我的文件是保存到磁盘里面的,所以输入设备是磁盘,当我们把文件拖拽到QQ对话框的时候,其实本质就是把文件加载到了内存中,然后通过打包封装,通过网卡这个输出设备用网络传输到你的网卡中,也就是你的输入设备中,然后发送过去之后,你看到的并不是文件的内容,而是文件的名字和文件的图标,那是因为你通过接受文件把该文件保存到了你的磁盘当中。
操作系统是一款进行软硬件资源管理的软件。
操作系统包括:
内核(进程管理,内存管理,文件管理,驱动管理)
其他程序(例如函数库,shell程序等等)
操作系统将软硬件资源管理好(这只是操作系统管理的一种手段),更重要的是要给用户提供良好的(易用,稳定,高效,安全)使用环境(这才是目的)。
举个生活中的例子,你呢,是一个大学生,步入了大学生活,我们都知道,我们大学四年跟辅导员打交道是最常见的,但是呢,跟校长打交道甚至有可能大学四年,校长的面都见不到,或者说毕业的时候可能能够见到,但是一般都见不到,这在我们大学生活中是比较常见的现象,但是呢,我们在哪个班,我们的姓名,学号,宿舍寝室,哪天哪节课,在哪上课,哪些学生成绩好,给哪些学生发奖学金却又是被安排的井井有条的,校长一直在管理着我们,管理的这么好,我们确一直没有见过他,这又是为什么呢?我们感觉一直是辅导员管理这我们,其实真正的管理者是这个学校的校长。那我们就好好的来谈谈什么是真真的管理者,我们生活中做的事情从宏观上来看,无非就分为两种,一种是做决策,一种是做执行。在学校我们躺在床上的时候是吃饺子呢?还是嗦粉呢?这叫做我们在做决策,后来我起床了,去吃饺子,这叫做执行。在我们生活中呢我们可能既做决策又做执行,但是真正的管理者基本上都是做决策或者少量执行,或者我们不谈执行,就是做决策。
比如说,最近响应学校开运动会的事情,运动会要不要开呢?校长决定开,那校长会不会一个一个下去通知每一个学生说:张三,明天下午两点运动会,记得来参加哦。 校长会这样做吗?答案是:不会。校长应该是找到学院院长或者体育老师通过开会决定开运动会之后,学院院长组织辅导员,辅导员组织学生们参加运动会。但是如果给你来作决策,会不会说,我今天想跑个步,让学校开一场运动会吧,我今天想吃面条,让学校食堂都换成面条,会不会呢?不会,所以呢我们这里谈到的做决策必须是一种正确的决策。那么如何能够做出正确的决策呢?依据是:根据大量的数据做决策,所以想要做出正确的决策我们前提条件得有完善的数据。
假设我是一个公司的领导,手底下有十个程序员,手上有10000块钱的奖金想要发下去,那么可以收集通过总结他们这一年中写了多少代码,出了多少bug,解决了多少bug,解决bug的速度怎么样,跟团队之间的沟通能力怎么样,一结合进行排名,那么就知道奖金如何发放了。
所以说我们一个真正厉害的领导者要想做出正确的决策是需要大量完善详细的数据的。
重新回到上面那个例子,假设就校长,辅导员,学生三个层次,其中校长就是管理者,学生是被管理者
辅导员收集学生的个人信息带到校长办公室给校长,校长通过这些数据信息进行做决策,所以我们可以得出一个结论:管理的本质不是管人,而是管理数据。
通过上述结论可以知道,为什么我们没见过校长,校长却能管理我们,见面只是形式上的,本质上真正被管理的是我们的数据信息。
那么如何管理好这些数据信息呢?
以学校的学生信息为例:学生都有各自的姓名,学号,性别,身高,成绩,紧急联系人,成绩等等信息,我们可以以表格的形式来存放,但是如果我们想让计算机管理起来,在C语言层面上我们就构建一个结构体来进行管理,C++来说就是一个类,我们也可以利用数据结构,比如说链表或者其他高效的数据结构进行管理。所以最后对学生的数据信息管理最后就转变成了对链表的增删查改。
类比到我们的操作系统当中就是操作系统通过管理这些数据结构来管理硬件设备。
这是对学生的管理的一个建模的过程。
最后都高度抽象总结成六个字:先描述,再组织。
操作系统管理的核心:
1.进程管理
2.内存管理
3.文件/IO管理
4.驱动管理
我们可以再来理解一下这的用户的含义:
广义上:所有人
狭义上:开发者
现在我们来谈的这个用户如果不做特别说明,说的就是我们的开发者。
那么我们下面用一个案例说明为什么会是这几层结构,每一层都充当什么作用呢,上面我们已经谈及到了下三层,下面我们对上面几层通过案例进行说明。
那我们如果现在想要知道系统的内存,用了多少,还剩多少,操作系统又是对内存进行管理的,那我们是不是可以直接找系统要就行了,因为我们前面说了,操作系统中一定有大量的对软硬件设备进行描述的结构体,我们前面已经说过了先描述,再组织。那我们用户想知道这些信息不是可以直接往结构体里面提不就完了吗?再是我们如果想要访问文件,那操作系统也对文件进行管理的,那我们是不是也可以直接访问操作系统啊?其实,这样做,在技术上是绝对可以实现的。但是,群众当中也有坏人啊,开发者当中也有坏人啊,有些开发者可能就是不走正途,就是为了盗取信息,篡改信息,如果操作系统直接把这些数据公开让用户随意访问,那么操作系统怎么去判定呢? 答案是:操作系统做不了这个判定,所以操作系统就决定:不相信任何用户。
那么你肯定会觉得非常奇怪,你这不是在跟我扯嘛?操作系统可是要给我们用户提供服务的,你现在居然不相信我,你不相信我,那操作系统怎么给我们提供服务。
那么我们可以发挥下想象,生活中有哪些不相信我们,确给我们提供服务的?
比如说:银行
银行相信我们嘛?银行如果相信我们的话,那么银行门口的保安是干什么的?银行如果相信我们的话,那银行里面那厚厚的玻璃是干什么用的?所以,银行就是典型的不相信我们却要给我们提供服务的例子。
所以银行会提供一个窗口(也就是一个接口),所以我们可以把这个窗口看作是操作系统上层的系统调用接口,用户想要使用哪些业务可以调用那个系统调用接口,类似于你在银行窗口外要存钱就使用存款业务,类比于你在计算机上面要访问某个文件,或者内存是通过系统接口调用然后操作系统通过一系列操作给你返回结果。
那么对于我们上面所谈到的六个字:先描述,再组织。该如何理解呢?
那么如果今天有一个人说:同学,你好,你能不能帮我描述一下一个香蕉是什么样子? 你能不能帮我描述一下你的同桌是什么样子?你能不能帮我描述一下一只羊是什么样子? 或者是一只狗。等等。那么如果今天所说的这些东西不存在或者没有见过,也就像是科学家发现新事物一样,那么你只能描述这个香蕉的大小,形状,能不能吃,能吃的话口感怎么样?这是水果还是什么?等等等等。
还有一种情况就是把香蕉摆在你的面前,你可能也只能提炼出香蕉的大小,形状,颜色等属性。
那么说了这么多,其实我就想说一个事情,那就是我们人是没有办法充分认识世界的,人是通过属性来认识世界任何事情/事物的!重要属性的集合就代表这个人或者事物。
而面向对象编程就是通过用属性来描述各种人或事物的。
上面我们谈到用户不能直接访问操作系统中的数据或者外设,如果想要访问这些软硬件资源就必须贯穿整个层状结构,如果贯穿整层状结构就必定要调用系统调用,所以操作系统可以通过系统调用实现保证自己的安全同时为用户提供安全的服务。而我们平时c语言用的printf函数,c++中的cout实现了在显示器中直接打印出来,那么就必定访问了外设,所以这两个函数必定封装了系统调用。
而系统调用使用起来比较麻烦,站在用系统的人的角度来看,怎么让系统易用呢?所以操作系统提供了一个外壳程序(linux是shell,图形化界面),外壳程序是用c/c++语言写的,一定会调用系统调用!
站在系统上开发人的角度,可以直接调用系统接口,将系统接口可以封装,成为各种好用的函数,打包形成库,所有的开发者,用很多功能,不用自己写了,而是直接调用库函数即可!也就是上图用户操作接口中的lib。专业的人做专业的事,提高开发效率,降低开发成本。比如我们学的c/c语言,经常调用c/c++标准库。
计算机管理硬件
1. 描述起来,用struct结构体
2. 组织起来,用链表或其他高效的数据结构
在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
那在还没有学习进程之前,就问大家,操作系统是怎么管理进行进程管理的呢?很简单,先把进程描述起来,再把进程组织起来!下节我们来学习进程。