【本节重点】
- 认识冯诺依曼系统
- 操作系统概念与定位
- 深入理解进程概念,了解PCB
- 学习进程状态,学会创建进程,掌握僵尸进程和孤儿进程,及其形成原因和危害
1.冯诺依曼体系结构
我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。
截至目前,我们所认识的计算机,都是有一个个的独立的硬件组件组成
- 运算器: 运算单元是计算机的核心,负责执行各种算术和逻辑运算,如加法、减法、乘法、除法以及比较操作。ALU根据控制单元发出的指令执行相应的计算任务。
- 控制器: 控制单元负责协调计算机内部各个部分的工作。它从内存中读取指令,解释这些指令,并生成控制信号,指导运算单元、输入/输出设备和存储单元执行相应的操作。控制单元是计算机的指挥官,确保所有的操作按照正确的顺序和时序进行。
- 存储器: 存储单元用于存储数据和程序。计算机的内存分为主存储器(RAM)和辅助存储器(如硬盘、固态硬盘),主要区别在于速度和易失性。主存储器用于存放当前运行的程序和数据,而辅助存储器用于长期存储数据和程序。
- 输入设备: 输入单元负责将外部的数据或指令引入计算机系统。输入设备可以包括话筒、摄像头、键盘、鼠标、磁盘、网卡等。输入单元将外部信息转换为计算机能够理解的形式,并传递给存储单元或控制单元进行进一步处理。
- 输出设备: 输出单元将计算机处理后的结果呈现给用户或其他设备。输出设备可以包括声卡、显卡、网卡、磁盘、显示器、打印机等。输出单元将计算机内部的信息转换为人类可读或其他设备可处理的形式。
这些独立的设备如果想要使用起来就必须要在物理上存在某种线路连接起来,但是我们拆开我们的计算机发现没看到这门多条线。每个独立的设备通过总线连接在一起,但是这些总线都被集成到主板上。主板是计算机内部的核心组件之一,它起到连接和支持其他硬件设备的作用。主板上集成了各种总线,通过这些总线,独立的设备如处理器、内存、输入输出设备等能够相互通信和协同工作。通过独立设备连接的手段,实现多个独立设备之间的数据流动的目的。
对冯诺依曼的理解,不能停留在概念上,要深入到对软件数据流理解上,我们先考虑设备之间的数据信号流动。
设备之间的数据信号流动本质是设备之间进行数据的来回拷贝,拷贝的整体速度,是决定计算机效率的重要指标。一个商品能被大众所接收,首先要稳定性效率都不错,其次是价格比较低。现在我们在来深入了解一下冯诺依曼以及背后的价值。
why1:为什么在体系结构中要存在存储器(内存)?
我们先来看一下计算机存储金字塔。
规律:距离CPU越近的存储单元,效率越高,造价越贵,单体容量小,反之,距离CPU越远的存储单元,效率越低,造价越便宜,单体容量大。
按照下面的结构可行吗?为什么要有存储器呢???
输入设备和输出设备这些都叫做设备,输入输出设备的速度通常较慢。例如,硬盘驱动器的读写速度相对较低,而键盘和鼠标等输入设备也有一定的延迟,而且这些设备都是距离CPU很远的存储单元,所以CPU直接访问这些设备都是非常耗时间的,而CPU的计算速度都非常快,所以这样就形成了快的CPU与慢的输入输出设备组合,这就好比我们的木桶原理,最短的木板取决于木桶存放水的储量,计算机也是如此,此时计算机的效率就取决于输入输出设备,完全以外设为标准,因此计算机会非常的慢。
此时CPU就一直在问输入设备,我已经等好久了,输入设备你输完了没有,待数据输完之后,CPU立马就计算出来,然后就给输出设备,然后就一直问输出设备,我已经给输出设备了,输出设备怎么还没写完。此时CPU就一直处于闲置等待的状态。
鉴于此问题,我们就需要插入一个存储器(内存)
前提:存储器的速度比外设快,比CPU慢。
所以以后输入设备的信息就给到内存,又内存再交给CPU,而CPU也不用把信息直接交给输出设备,而是由内存交给输出设置。就比如在现实生活中,一个工程由一个急性子(CPU)和一个慢性子(外设)的人共同完成,此时工程的进度肯定由慢性子(外设)慢性子决定。但是后面我们加入一个速度不快不慢(内存)的人,让这个人去帮一下慢性子(外设),帮慢性子(外设)的人解决一部分问题,由此这个工程的完成效率就能提升。
引入内存之后就可以保证计算机的整体速度不要以外设为标准,而变成以内存为标准设定计算机的整体速度。但是这里不对呀?上面的外设还是存在的,此时不应该还是取决于外设吗?木桶原理的那个最短木板还在呀!本来CPU可以直接拷贝外设的数据,现在要将数据通过外设拷贝内存上,然后再拷贝到CPU上才能进行计算,那我们这不是选择了一条远路,而且这条路还绕。那这样效率不是更低吗?
其实不然,内存把输入设备要输入的多批数据,在CPU还没有访问的时候再做其他计算的时候,提前外设要输入的多批数据拷贝到内存(预先加载),当CPU忙完计算时,CPU就直接将内存的数据拷贝过来,这也速度就提升了很多。同时CPU计算完后,只需要将数据写入内存,然后外设再慢慢读取内存(缓存)的信息输出结果即可,这样CPU只用和内存打交道,内存此时看像一个巨大的缓存,介于设备和CPU之间,整体上宏观上提升了速度和效率。
内存:预存任务、缓存结果,计算机的效率最终变成了以内存效率为主。因为内存的引入,不仅计算机的效率有了很大的提升,同时价格比较便宜。冯诺依曼结构巧妙的把效率问题转化为软件问题。
程序在运行的时候,必须把程序先加载到内存中,为什么?
首先我们的程序是一个文件,文件是存放在电脑磁盘中的,磁盘是外设,而程序中存放了很多指令和数据,这些最终都是要CPU去执行的,而这些指令和数据需要通过外设拷贝到内存,然后再由内存交给CPU才能执行。在数据层面,CPU只和内存打交道,外设只和内存打交道,内存起一个核心作用,而这是由于冯诺依曼体系结构规定的。
解释,从你登录上qq开始和小美聊天开始,发送"我喜欢你"这个字符串,整个数据的流动过程。
你和小美各自使用一台电脑,那么就各自有一套冯诺依曼体系结构,当你在键盘输入信息时,这个信息会被加载到你电脑的内存中,然后再由CPU对你送的信息进行打包加密,CPU执行完后返回给到内存,内存交给网卡,再通过网络,传输到小美的网卡上,此时网卡作为输入设备,将你刚刚发送的信息给到内存,内存传给CPU后,CPU对信息进行解包解密,CPU执行完后返回字符串信息给到内存,内存交给显示器,因此小米才能收到你的表白信息。
如果是在qq上发送文件呢?
文件存放在磁盘上,此时就从磁盘上读取到文件给到内存,发送文件和发送消息数据流动差不多,唯一的区别就是两种发送的容量大小不同,文件最终会被输出到小美电脑聊天窗口,当小美点击下载的时候,此时文件就被下载到磁盘当中,第二天小美将电脑重启,依然能够看到这个文件。
2.操作系统(Operator System)
前言:在我们的计算机里,第一个加载的软件不是qq,不是微信。实际上我们电脑加载的第一款软件是操作系统,当我们电脑想要开机,加载的那一段时间,就是系统在加载操作系统时间。
2.1.概念
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:
- 内核(进程管理,内存管理,文件管理,驱动管理)
- 其他程序(例如函数库,shell程序等等)
2.2.设计OS的目的
- 与硬件交互,管理所有的软硬件资源
- 为用户程序(应用程序)提供一个良好的执行环境
2.3.定位
在整个计算机软硬件架构中,操作系统的定位是:操作系统是一个进行软硬件资源管理的软件。
2.4.如何理解 "管理"
首先我们来看一下计算机的层状结构。
今天我们先来看硬件层面,底层硬件是通过冯诺依曼体系结构连接起来的。操作系统(OS)通过相关的驱动程序来控制底层硬件。操作系统是一种软件,它提供了一个抽象层,使应用程序能够与硬件进行交互,而无需直接处理底层硬件细节。
- 操作系统(Operating System,OS):
- 操作系统是计算机系统中的核心软件,负责管理和协调计算机硬件和软件资源,提供用户和应用程序与硬件之间的接口。
- 它为应用程序提供了一个抽象的环境,使它们能够在不同的硬件平台上运行,而无需直接处理底层硬件细节。
- 操作系统通过调度进程、管理内存、文件系统和网络等功能来确保计算机的高效运行。
- 驱动程序(Device Drivers):
- 驱动程序是操作系统与硬件之间的桥梁,用于实现操作系统与硬件设备之间的通信和交互。
- 每个硬件设备都需要相应的驱动程序,这些驱动程序包含了硬件设备的控制指令,使操作系统能够正确地与硬件设备进行通信。
- 驱动程序提供了一个标准的接口,使得操作系统可以通过这个接口与硬件设备进行通信,而无需了解硬件的具体细节。
- 注意:驱动程序并不能决定底层硬件什么时候启动,什么时候释放,这些都是由操作系统决定的。
- 底层硬件:
- 底层硬件包括计算机的各种物理组件,如中央处理器(CPU)、内存、硬盘、显卡、网卡等。
- 驱动程序需要了解底层硬件的特性和功能,以便正确地管理和控制这些硬件资源。
- 操作系统通过驱动程序与底层硬件进行交互,以执行各种任务,如读写文件、处理输入输出、管理内存等。
在计算机系统中,操作系统、驱动程序和底层硬件形成一个层次结构,操作系统位于最上层,通过驱动程序与底层硬件进行通信。这种分层结构的设计使得操作系统和应用程序能够更容易地适应不同的硬件平台,同时提供了一个统一的接口,简化了软件开发和硬件管理的复杂性。
操作系统是一个进行软硬件资源管理的软件。何为管理,如何管理???
现实生活中每个人做事情,都在做决策和做执行,比如某天中午你起来饿了决定吃面条还是麻辣烫,这就是做决策,然后你决定去吃面条,这就是做执行。什么叫做领导呢?在管理体系中,领导充当做决策的人, 所以管理者(操作系统)就是做决策的人,而被管理者(硬件部分)就是做执行的人。
学校管理的例子
怎么理解先描述,后管理呢?我们以面向对象语言为例
我们也可以回顾一下我们之前写的C语言版通讯录
我们所有编程语言除了C语言,其他语言基本上都是面向对象的,所有的语言都要提供类似于C++的STL容器,java的集合类这样的东西,因为编程语言本质就是对数据进行管理。
未来我们如果想要写一个教务管理系统,首先就要先描述,通过struct或者class描述学生对象的属性(学号、姓名...),然后再组织,将学生对象的属性放到某些容器(数据结构)中,从而可以把对数据的管理场景转化为对特定数据结构的增删查改。
将教务系统管理这个具体的问题,进行计算机级别的 建模过程!转化为计算机能够认识的问题。
总结 计算机管理硬件
- 1. 描述起来,用struct结构体
- 2. 组织起来,用链表或其他高效的数据结构
现在我们再向上谈论一下,为什么要有操作系统?
操作系统充当计算机硬件和应用程序之间的中介,提供了一个有效且方便的计算环境。没有操作系统,计算机将是一个集合了硬件组件但缺乏组织和协调的庞大机器。操作系统的存在使得计算机能够更容易地被人类使用,提高了计算机的效率和可用性。
操作系统是一款管理软硬件资源的软件,那么问题也可以转化为什么要有操作系统的管理?
操作系统的管理是为了有效地协调和控制计算机系统中的各个组件(对下的手段),以提供一个稳定、高效、安全的计算环境(对上的目的)。
怎么体现稳定,安全的环境呢?
如果用户能够直接进入操作系统,那么用户就可以直接访问内部的数据,用户可以直接修改某些数据,这样很不安全,就相当于去银行取钱,取钱存钱都是自己去银行的金库拿,那么银行肯定会很担心,万一有人多拿了怎么办?因此银行就设置了一个窗口,根据用户的诉求,窗口的工作人员负责用户的取钱存钱的功能,而我们的计算机也提供了这样一个窗口:系统调用接口,应用程序通过系统调用提出诉求,由操作系统去完成应用程序请求操作系统核心功能和服务的机制。
2.5.系统调用和库函数概念
- 在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口(函数),供上层开发使用,这部分由操作系统提供的接口(函数),叫做系统调用函数。
- 系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统 调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
凡是函数那就会由输入和输出,比如在银行,你取钱的时候将身份证交给窗口内部的工作人员(输入),由他帮你核实信息,待工作人员核实完毕,按照你的取钱要求,将钱和身份证给到你(输出)。操作系统根据输入输出就能够给上提供数据上面和功能上面的支持。任何人都不能直接访问操作系统中的数据,只能通过操作系统提供的系统调用函数去获取数据和达到自己的请求。
用户能不能跨越操作系统,直接访问底层硬件?
一旦我们确立了操作系统为管理者,就不能由任何跨越操作系统的动作,必须要贯穿操作系统。这是为了确保系统的稳定性、安全性和可控性。
printf输出信息是如何打印到硬件显示器上
当你在程序中使用 printf 函数时,它会将格式化的数据发送到输出流(stdout)。在大多数标准的桌面操作系统中,stdout 默认指向屏幕终端。这些操作系统会提供一些底层的系统调用和驱动程序来管理这个输出的显示。
对于硬件显示器,例如在嵌入式系统中,printf 函数的输出通常需要一个底层的驱动程序或操作系统支持,以便将数据发送到硬件显示设备。这个驱动程序可能会直接操作显示器的硬件寄存器或者与显示控制器进行通信,将 printf 输出的数据传输到显示器的缓冲区中,然后显示在屏幕上。
用户如何可以调用操作系统提供的系统调用接口?
当然可以,但是我们调用比较繁琐,就相当于一个大爷去银行取钱,银行要求大爷填一些信息单,但是大爷不识字,为了解决这个问题,此时银行就提供了一个角色:大堂经理,大爷只负责告诉大堂经理信息,由大唐经理帮大爷解决这些问题。大堂经理就相当于计算机中的lib库(银行流程都清楚),负责提供服务,系统调用一旦由我们的操作系统向上提供,我们想使用这个系统调用就必须要对操作系统有一定程度上的理解,所以就有人对系统调用进行了封装,形成对于的lib->库,此时就减少了用户的使用成本,普通用户通常会通过编程语言或库函数提供的高级接口来使用操作系统的系统调用。
使用printf函数不需要关注底层是Windows系统还Linux系统的原因。
编程语言的标准库通常是具有跨平台性的,它提供了一组标准的、可移植的接口和功能。例如,C语言的标准库(如 、 等)在不同平台上具有相似的实现,使得基于这些库的代码更容易移植。同时,很多语言还有丰富的第三方库,这些库的设计目标之一就是提供跨平台的支持,使得开发者能够更方便地在不同系统上使用相同的代码,这样我们就屏蔽了系统调用接口的差异性。
2.6.承上启下
那在还没有学习进程之前,就问大家,操作系统是怎么管理进行进程管理的呢?很简单,先把进程描述起来形成一个struct或者class,每一个进程就是一个struct或者class对象,再把进程使用链表或者其他数据结构组织起来,进而把对进程的管理自然转化为对链表的增删查改!
【计算机系统基石与Linux进程管理深度解析】(二):https://developer.aliyun.com/article/1425712