目录
1、冯诺依曼体系结构
1.1 冯诺依曼体系结构的组成
1.2 程序运行时必须要加载到内存
1.3 数据通信
1.4 为什么要有内存
2、操作系统
2.1 概念
2.2 设计OS的目的
2.3 如何理解管理
2.4 系统调用和库函数的概念
1、冯诺依曼体系结构
我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。
1.1 冯诺依曼体系结构的组成
冯诺依曼体系结构主要由输入设备、输出设备、存储器、运算器、控制器组成。
输入设备:键盘、鼠标、网卡、磁盘、摄像头、话筒等等
输出设备:显示器、磁盘、网卡、打印机等等
输入设备和输出设备统称外设,也就是外部设备
存储器:实际上就是内存
运算器和控制器统称为中央处理器:也就是CPU
外存是指以磁盘为代表的具有存储功能的外部设备
1.2 程序运行时必须要加载到内存
我们之前常常听到这样一句话:任何程序,运行的时候,都必须先被(从磁盘)加载到内存
要弄明白这句话,就必须要了解清楚冯诺依曼体系结构是如何运行的。
从图中黑色线条的控制信号可以看出,CPU是可以直接向外设发送控制信号的,但是对于数据信号,必须通过存储器也就是内存与外设进行交互。我们写的源文件,编译生成二进制可执行程序后,就是一个文件,默认是存储在磁盘上的,磁盘是外设,二进制程序就是代码+数据,代码需要CPU执行,数据需要CPU计算,都需要CPU,所以一定需要将可执行程序交给CPU。但是磁盘是外设,在数据层面是无法与CPU进行交互的,必须借由内存。所以,要先将文件从外设拷贝到内存,内存将文件拷贝到CPU,CPU将处理结果拷贝回内存,内存再将数据刷新到外设。
所以,为什么任何程序,运行的时候,都必须先被(从磁盘)加载到内存?答案:是体系结构决定的
之前写进度条时,要有缓冲区的存在,缓冲区就是一块内存空间,运算器更新完结果后,数据是更新到内存中的,再由其他控制命令将数据刷新到设备上。没有缓冲区是无法完成这一过程的。
在IO流中,Input就是将数据从输入设备拷贝到存储器,Output就是将数据从内存刷新到输出设备
scanf就是将键盘作为输入设备
1.3 数据通信
我们来简单模拟一个两个人使用聊天软件聊天时的数据通信
A和B通过电脑使用QQ进行聊天,A和B的电脑都是冯诺依曼体系结构,因为还没学网络,所以中间的网络部分就忽略掉。QQ是一个软件,运行起来后就会变成一个可执行程序,并加载到内存中。键盘作为输入设备,输入数据后,将数据从输入设备加载到内存是通过QQ来完成的。
加载到内存后,CPU就会从内存读取数据,通过QQ对数据进行运算、加密等,再将处理结果写回内存。电脑中连接网络的设备是网卡,所以将处理好的结果从内存写到网卡
通过网络就可以将数据发送到对方的输入设备上,对方的输入设备的网卡。接着输入设备将数据加载到内存,CPU从内存中读取数据,对数据进行解密等,再将处理结果写回内存,内存将处理结果刷新到输出设备,这里的输出设备是显示器。
1.4 为什么要有内存
在冯诺依曼体系结构中,CPU要与外设进行数据层面的交互时,都必须要经过内存,那为什么一定要有内存呢?我们先来看一个计算机内的存储金字塔
会发现计算机中离CPU近的硬件,如寄存器,缓存,内存等,容量小,速度快。若无内存,CPU直接与外设打交道,计算机的效率就是由外设的效率决定的。若有内存,CPU与内存打交道,读写效率就由内存决定,外设也与内存打交道,因为内存空间较大,所以可以用一些算法将外设的数据提前写入内存,从而提高效率。当然,若想极致地快,可以使用寄存器去充当内存,但是这样造价高昂。所以,有内存,是以较低的成本,完成较高的效率。
所以,当数据在计算机内部流转的时候,本质是在不同设备间进行拷贝,设备的拷贝效率就是计算机的效率
2、操作系统
2.1 概念
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:
内核(进程管理,内存管理,文件管理,驱动管理),内核主要由这四大块构成
其他程序(例如函数库, shell程序等等)
宏观上操作系统是一整套的,往后说的操作系统往往指的是操作系统内核
2.2 设计OS的目的
我们来看一张从用户到计算机底层的图
会发现,计算机的整个软硬件结构是层状结构的
操作系统对于计算机内的软件:如开启APP,新建文件等,是通过操作系统完成的
操作系统对于计算机内的硬件:如内存、磁盘、显卡等,通过驱动程序对硬件做管理,硬件并不是由操作系统直接访问的,每一种硬件都必须要有对应的驱动程序,操作系统通过控制驱动程序来控制硬件,如硬件读取到的数据,操作系统不会向硬件要,而是向驱动程序要。操作系统最先开始会安装部分驱动,这部分驱动对应的硬件可以直接使用,若想要使用没有安装驱动程序的硬件,需要先安装驱动程序。
用户操作窗口中,就有C/C++的库、指令等
从上面的层状结构可以看出:
1. 操作系统对下进行软硬件资源的管理,保证软硬件能够稳定地、高效地、安全地进行工作(手段)
2. 操作系统对上要给用户提供一个稳定的、高效的、安全的运行环境(目的)
设计操作系统的目的:通过对下进行软硬件资源的管理,保证软硬件能够稳定、高效、安全地工作,以达到操作系统对上提供给用户一个稳定、高效、安全的运行环境的目的。
2.3 如何理解管理
我们首先来看上面图片中的下三层,操作系统是如何对软硬件进行管理的
我们可以举一个例子,我们将大学抽象成一个校长、几个辅导员、非常多的学生,校长要对学生进行管理,但是校长与学生是不会见面的,校长是如何一个人管理这么多学生的呢?实际上,管理的本质是对数据进行管理,只要管理者能够拿到被管理者的数据,就能将被管理者管理起来。所以,校长并不需要和学生见面,只要能够拿到学生的成绩,就能够将学生管理起来。同时,管理者与被管理者之间还需要有一个角色,这个角色对上,将采集、获取到的数据,交给管理者,对下,传达管理者的指令,并执行管理者的决策。在这里面,操作系统就是校长,驱动程序就是辅导员,底层硬件就是学生。
我们通过这个例子了解到了在一个管理系统中,管理者的作用就是:根据被管理者的数据,来进行决策下一步需要做什么事情,或者需要对原先的事情做出什么样的调整
假设我们现在是一个管理者,也就是校长,全校有2w名学生,我们要如何管理好这2w名学生呢?
前面说了,管理的本质是对数据进行管理,所以,我们需要先将这2w名学生抽象成数据,每一名学生都有姓名、性别、年龄、籍贯、身高、成绩等等的属性,我们可以通过这些属性来对学生进行管理。在C语言中,我们可以使用一个结构体来保存每一个学生的属性
struct student
{
char name[64];
int sex;
float score;
...
};
通过使用结构体,就可以定义不同的对象,每一个对象都是一个学生的属性。但学校有2w名学生啊,定义2w个对象要如何组织起来呢?此时就需要使用到数据结构了,我们这里简单地使用链表
struct student
{
char name[64];
int sex;
float score;
...
struct student* next;
};
这样,我们就将校长对学生的管理,变成了对链表的增删查改操作。同时,我们也完成了对于学校学生管理工作的一个计算机层面的建模工作。
在操作系统管理底层硬件时,与校长管理学生是类似的。每一种硬件都会有属性,并且这些硬件的属性可以是相同的。操作系统内部会封装一个结构体,假设弄成链表结构。一旦识别到一个新设备,通过驱动程序就可以报告给操作系统,操作系统就可以做出相应的调整。
这种管理思想称为先描述,再组织。任何计算机对象,管理思想均为先描述,再组织。
所以,为什么现在主流的编程语言都要提供:1.面向对象 2.标准库,如C++
语言提供的面向对象,可用来描述属性,标准库可用来组织。所以可以直接使用编程语言来完成被管理对象的先描述,再组织,进而完成一整套系统。
操作系统要做管理,会定义大量被描述起来的对象,如网卡、硬盘、内存、文件、进程,并且有大量的数据结构,各种管理,都会变成对数据结构的增删查改
是先有的操作系统,再有的语言
为什么要有数据结构?
最先开始时,只有语言,以及操作系统,无论是操作系统,还是其他软件,都需要先描述,再组织。为了支持再组织,就有了数据结构。(数据量太大时,一定需要再组织)
为什么要有面向对象?
写软件时,最后就会变成怎么样去将一个对象描述起来,用struct太麻烦
有了面向对象和数据结构,就可以使用语言进行更好地管理了
2.4 系统调用和库函数的概念
接下来我们看上面图片中的上三层
我们再来举一个例子,银行也是一个系统,里面有行长、工作人员、底层的硬件(如设备、仓库、宿舍、桌椅),每一种硬件都有对应的维护人员。当客户要来银行中办理业务时,不可能让客户去直接使用银行内的硬件,如直接自己将钱放进仓库,这是不安全的。所以,银行会对外开发许多的窗口,当客户需要办理业务时,就去对应的窗口办理。所以,整个银行系统是通过窗口来保证对外提供服务的,对于操作系统也是如此。上层用户不能绕过操作系统直接操作硬件,即操作系统是封闭的,为了让用户能够操作,就需要给用户提供接口,提供的这些接口,就是系统调用。用户只能通过系统调用使用操作系统。
我们需要知道,操作系统是C语言写的,所以接口是C语言接口。C语言中的scanf和printf是C语言封装的函数,底层是一定要调用系统调用的。cin和cout是C++中类实例化出的对象,类中的成员方法也是需要调用系统调用的。C/C++可以直接调用系统调用,与调用函数没有区别。java等其他语言,也是需要通过C语言来调用系统调用的,像java中有虚拟机,java的所有程序都是在虚拟机上跑的,虚拟机就是C语言写的,通过C语言来完成系统调用。所有软件底层,都必须直接或间接与C相关
为了方便用户进行操作,可以将系统调用封装成库,像glibc是C标准库,libc++是C++标准库。注意,不是所有的库都需要封装系统调用,如只使用CPU资源,而不使用操作系统资源的库,C语言中的math.h库就是
所以,我们现在要操作操作系统,有两种方式,可以直接使用系统调用,这就类似于去银行中直接去银行开设的窗口办理业务,也可以使用封装的库,这就类似于通过银行的大堂经理完成业务的办理。
这里插入一个题外话,图形化界面也是一个用户操作接口
图形化界面本质就是访问显示器,显示器是一个二维坐标,上面有很多像素点,若某一区域是绿色的,只是这一区域的像素点被绿色点亮了,本质是将像素点按照运算规则刷新到显示器上,与printf打印字符没有任何区别。图形化界面中,点击某一区域就会被操作系统识别,识别后,就会将鼠标点击的行为转换为系统调用接口。安卓就是linux内核 + 图形化界面。国内大部分的APP都是基于图形化界面提供的上层接口,所以图形化界面也要配一个库,此时就是安卓开发。