计算机是如何运行的
目录
一,计算机是如何组成的
1.1,CPU中央处理单元
1.1.1,CPU的构成和属性
1.1.2,如何判断cpu的好坏
1.1.3,指令
1.1.4,CPU的缓存
1.2,操作系统
1.2.1,进程
1.2.2,PCB的核心属性
1.2.3,内存分配-内存管理 和进程间通信
一,计算机是如何组成的
在冯诺依曼的体系中,计算机由CPU,存储器,输入设备和输出设备组成
1.1,CPU中央处理单元
1.1.1,CPU的构成和属性
门电路=>半加器=>全加器=>加法器=>ALU运算器=>差不多构成CPU
这是电脑是计算机的属性:
AMD指的是生产CPU的厂商,记住主要的厂商是intel 和 amd,它们生产的区别是intel的针脚长在主板上,amd的针脚长在CPU上
7840H是指这是标压处理器,通过H这个后缀进行判断,其中还有U系列,不同的字符代表不同的性能和功耗级别,U表示的是低压CPU
3.80GHz表示的是CPU的主频,也就是指CPU一秒钟可以执行多少条指令,执行的每个次数,又被称为时钟周期
1.1.2,如何判断cpu的好坏
判断CPU的好坏有很多指标,但最关注的只有两点:主频 和 核心数
在打开任务管理器找到CPU的时候,可以看见CPU的数据:
其中3.32GHz和之前查看处理器的性能时的主频不一样,是因为cpu主频都是在时刻改变的~~它会根据当前任务的负载程度,动态变化
3.32GHz就是指运行是当前的频率,又被称为睿频
CPU的频率是有上限的,不同的CPU上限不一样,甚至有的CPU还可以超频,给CPU吃更多的电,CPU就有更强的表现
内核指的就是CPU的核心数
其实最开始的时候cpu都是单个核心的(核心可以理解为一个能够完成完整计算机功能的整体,是由很多的计算机单元构成的),提高集成程度,就提高cpu的速度
随着时代的发展,随着集成程度的提高,发现进一步提高,就越来越难了~~减小单个计算单元的体积,势必就会增加工艺的难度~~当体积小到一定的程度的时候,经典力学就失效了,量子力学就接管了
于是一个核心不够,就多个核心来凑
内核就是指cpu上焊上去的核心,现在的cpu有一个"超线程技术",可以让一个核心顶两个核心,就指的是内核下方的逻辑处理器
1.1.3,指令
指令(Instruction)是cpu上能够执行的任务的最小单元,这些最小单元都是由二进制的方式来表示的机器语言(不同的cpu支持的指令/机器语言是不相同的)
简单模拟cpu执行指令的过程:(这是简化的版本,真实的X86或者arm的指令表要复杂很多)
RAM:内存
寄存器:cpu上的存储数据的单元,cpu上能直接存的数据比较少,这些寄存器主要是为了支持cpu完成一些运算,保存中间结果的,它的空间虽然有限,但是访问速度是极快的,比内存访问速度要快上3-4个数量级
这一段指令 其实就是内存中的一段数据的单元~~我们写好的代码,最终想要运行,都是需要让操作系统,先把写好并编译好的指令加载到内存中,然后cpu才能执行的 假定,从0号地址开始执行程序,cpu就会先从0号地址这里读取数据,到cpu寄存器里,并对这个指令 进行解析=>查询指令表,看这个指令要干嘛 0010 1110,前4位对应的是opcode,0010即指LOAD_A 要完成的工作,从内存中,读取数据到A寄存器中,后4位是参数,是内存地址,转换为十进制,1110就是14 那么这里就是指将14地址内存的数据读取到A寄存器当中 默认情况下,cpu执行内存中的指令是''顺序执行''的,除非遇到跳转类的指令 后面的LOAD_B和STORE_A执行也是同理了 ADD指令中,1000 01 00,1000指执行ADD,01和00分别指向不同的寄存器,其中寄存器的编号都是在指令表里提前要约定好的,将两个寄存器里面的内容相加,结果保存到第二个操作数的寄存器中
1.1.4,CPU的缓存
当时的计算机,在cpu执行指令的时候,要经历从内存中读取数据的操作,这个设定,就是冯诺依曼体系的精髓 最初设计该结构,就是为了把"执行"和"存储"分开,这么做主要是为了"解耦合"来降低硬件设计的成本 且当年的cpu执行指令的速度和存储器取指令的速度是差不多的,配合很好
随着硬件技术的发展,cpu越来越快,内存读取数据提升不明显,内存逐渐跟不上cpu的节奏了
于是出现缓存,通过临时存储经常访问的数据,提高数据检索速度和应用程序性能
1.2,操作系统
像windows10,windows11,linux,mac os,android,ios都是操作系统,这些操作系统,本质上都是用来搞管理的软件
操作系统的功能主要是两点:
1.对下管理所有的硬件设备
2.对上要给软件提供一个稳定的运行环境
对于第一点,操作系统毕竟是一个软件,不可能认识市面上的所有的硬件设备
但是操作系统知道,市面的硬件设备就这么几个大的类别,每个大类别下面的硬件设备大概有哪些功能
硬件厂商就需要在开发硬件的时候,同时开发一个驱动程序,专属于这个硬件设备,让操作系统通过这个驱动程序完成对硬件设备的控制,也就是指操作系统统一管理各种不同的硬件设备给软件提供统一的api
注:由于JVM已经把系统api封装了,完成同样的功能,就直接调用jvm的api即可,不需要学习系统原装的,(天然跨大平台)在windows上能跑,换成linux等其他的也能够跑
1.2.1,进程
进程是操作系统提供的一种"软件资源"
如今我们使用的系统,都属于是"多任务操作系统",也就是同一时刻,可以同时运行多个任务
电脑上每一个正在运行的程序,就可以称为是"任务",也叫做"进程"
与之对应的,就是"单任务操作系统",同一时刻,只能运行一个程序
每个任务在执行过程中,都需要消耗一定的硬件资源
换而言之,计算机中的每个进程,在运行的时候,都需要给他分配一定的系统资源
因此,进程是系统分配资源的基本单位
操作系统的进程管理:
1.先描述(使用类/结构体这样的方式,把实体属性给列出来)
操作系统,一般都是C/C++实现的,因此可以使用结构体
表示进程信息的结构体,称为PCB(进程控制块,Process Control Block)
2.再组织(使用一定的数据结构,把一些结构体/对象 串到一起)
当我们看到任务管理器中的这些进程的时候,意味着系统内部就在遍历链表,并且打印每个节点的关键信息
如果运行一个新的程序,于是系统中就会多一个进程,多的这个进程就需要构造出一个新的pcb,并且添加到链表上
如果某个运行中的程序退出了,就需要把对应进程的pcb从链表中删除掉,并且销毁对应的pcb资源
此次的表述是一个简化版本,事实上组织方式更加复杂(不是一个链表,是更加复杂的链式结构)
进一步了解进程,就要去了解PCB
1.2.2,PCB的核心属性
pid:进程的身份标识,此处通过一个简单的不重复的整数来进行区分的。
系统会保证,同一个机器上,同一时刻,每个进程的pid都是唯一的~~
内存指针:描述了进程使用内存资源的详细情况,进程运行过程中,需要消耗一些系统资源的,其中内存就是一种重要的资源,只要从系统中申请,系统分配一块内存,才能使用,每个进程都必须使用自己申请到的内存.内存指针,就是用来描述说你这个进程,都能使用哪些内存,一个进程跑起来的时候,需要有指令也需要有数据(指令和数据都是要加载到内存中的),进程也需要知道,哪里存的是指令,哪里存的是数据
文件描述符表:描述了进程所涉及的硬盘相关的资源,我们的进程经常要访问硬盘,而操作系统,对于硬盘这样的硬件设备,进行了封装=>文件,不管是哪种盘,都是统一进行的抽象,都是按照"文件"的方式来操作的
一个进程想要操作文件,就需要"打开文件",就是让你的进程在文件描述符表中分配一个表项(构造一个结构体)表示这个文件的相关信息
正因为进程是系统分配资源的基本单位,所以内存,硬盘就会在PCB中有所体现
过渡:
在任务管理器,可以看到进程消耗了cpu的资源
cpu就像一个舞台,而要执行的指令,就是演员,而指令是进程来执行,演员也就是进程
一个cpu可能有一个核心,也可能有多个核心~~
每个核心都是一个舞台,演员需要登上舞台,才能够进行表演,但同一时刻,一个舞台上,只能有一个演员
假如一个电脑上有16个逻辑核心,而系统上的进程,远远不止16个,不够分怎么办
所以,这里就涉及到一个非常关键的概念~分时复用(并发)
当cpu核心只有一个时,先执行进程1的代码(进程1,登台表演),执行一会后,让进程1下来,进程2上,进程2执行一会后,进程3上,以此类推
只有切换速度足够快,人是感知不到这个切换的过程的,在人眼中,多个任务/进程,就是"同时执行"的,而当进程太多,cpu负担太重,就会出现"卡顿"
随着多核cpu出现,同时执行的进程就变得更加复杂了
如有4个舞台,同时就可以有四个不同的进程,在各自的舞台上进行执行,此时,微观上,这几个进程也是"同时执行的",而不是靠快速切换模拟的"同时执行",被称为并行执行
与之对应的,前面的并发执行,仍然存在,每个核心仍然要分时复用,仍然要快速切换
所以当前现代的计算机的执行过程,往往都是并发+并行同时存在的,而对于两个进程是并行执行还是并发执行就都是看系统的调度的
因此,往往就把"并行"和"并发"统称为"并发"
所以此次cpu的百分数,就是指你的进程在cpu舞台上消耗的时间的百分比 如果有一个进程,把cpu吃到了100%,意味着其他进程都没有执行的时间了,很可能就会造成系统卡顿,于是就要用到进程的调度,分时复用,并发执行
对此,PCB中就需要提供一些属性,来支持系统对这些进程的调度:
状态:描述某个进程是否能够去cpu上执行
状态中重要是就绪状态和阻塞状态
就绪状态:随时准备好去cpu上执行,操作系统打声招呼就可以上了
阻塞状态:这个进程,当前不方便去cpu上执行,不应该去调度他(比如,进程在等待IO,来自控制台的输入输出)
优先级:对于多个进程等待系统调度,调度的先后关系,先调度谁,后调度谁,谁长,谁短,都是可以进行调配的(系统的api可以设置)
记账信息:针对每个进程,占据了多少cpu时间,进行一个统计。会根据这个统计结果来进一步的调整调度的策略~~
因此就需要在下一个轮次进行调整,确保每个进程都不至于出现完全捞不着CPU的情况的
上下文:进程从cpu离开之前,需要保存现场,把当前cpu中各种寄存器的状态,都记录到内存中
等到下一次进程回到cpu执行的时候,此时就可以把保存的这些寄存器的值恢复回去,进程就会沿着上次执行到的位置,继续往后执行
就相当于存档和读档
结合前面指令执行,知道每个进程在运行过程中,就会有很多的中间结果,在CPU的寄存器中
例:3和14相加,先使用寄存器保存3和14,再使用寄存器,保存17
然而执行完3加14后,进程就被调度出了cpu
操作系统调度进程,过程可以认为是随机的,任何一个进程,代码执行到任何一条指令的时候都可能被调度出cpu,因此,就需要在进程调度出cpu之前,把当前寄存器中的这些信息,给单独保存到一个地方(存档)
在进程调度回cpu的时候,继续之前的进度来执行,在该进程下次再去cpu执行的时候,再把这些寄存器的信息给恢复过来(读档)
"保存上下文":就是把cpu的关键寄存器中的数据,保存到内存中(PCB的上下文属性中)
"恢复上下文":就是把内存中的关键寄存器中的数据,加载到cou对应的寄存器中
1.2.3,内存分配-内存管理 和进程间通信
内存管理的核心结论:每个进程的内存,都是彼此独立的,互不干扰的
通常情况下,进程A不能直接访问进程B的内存,为了系统的稳定性,如果某个进程代码出现bug,出错影响的范围,只是影响到自己的这个进程,不会影响到其他进程,这种情况,也称为"进程独立性"
进程间通信:
虽然有进程的独立性,但是有时候也需要,多个进程相互配合,完成某个工作
进程间通信与进程的"独立性"并不冲突,系统提供一些公共的空间(多个进程都能访问到的),让两个进程借助公共空间来交互数据
上述只是进程的序幕,实际上,在JAVA中不太鼓励"多进程编程"
线程 更加重要了,详细看线程单独的文章