目录
一、冯诺依曼体系
二、CPU基本流程工作
逻辑⻔
电⼦开关——机械继电器(Mechanical Relay)
⻔电路(Gate Circuit)
算术逻辑单元 ALU(Arithmetic & Logic Unit)
算术单元(ArithmeticUnit)
逻辑单元(Logic Unit)
ALU 符号
寄存器(Register) 和内存(RAM)
控制单元 CU(Control Unit)
指令(Instruction)
三、CPU的基本工作流程
总结:
四、操作系统
五、进程 / 任务(Process / Task)
操作系统的进程管理
PCB的一些核心属性
pid
内存指针
文件描述符表
CPU在pcb中的体现
并发和并行:
状态
优先级:
记账信息:
上下文:
进程的内存分配:
进程间的通信:
都看到这了,点个赞再走吧,谢谢谢谢谢!!!
现代的计算机,大多是遵守冯诺依曼体系结构
如图:
各个部分的分工:
• CPU中央处理器:进⾏算术运算和逻辑判断。
• 存储器:分为外存和内存,⽤于存储数据(使⽤⼆进制⽅式存储)。
• 输⼊设备:⽤⼾给计算机发号施令的设备。
• 输出设备:计算机个⽤⼾汇报结果的设备。
针对存储空间进行比较:硬盘 > 内存 >> CPU
针对数据访问速度进行比较:
CPU >> 内存 > 硬盘
门电路 => 半加器 => 全加器 => 加法器 => ALU运算器 => 差不多构成CPU
通过电⼦开关,我们可以实现 1 位(bit)的看似⽆⽤的逻辑运算,但⾄少它⼯作起来了,不是么。怎么使⽤电⼦开关组合出真正有⽤的逻辑组件。
以后的真空管、晶体管的实质也是完成类似的⼯作,只是物理原理更加复杂,就做深⼊解读了。
ALU 是计算机中进⾏算数、逻辑运算的核⼼部件,是计算机的数学⼤脑。接下来,我们⽤上⼀节构建的逻辑⻔来完成⾃⼰的⼀个 ALU,去学习理解它的⼯作模式,以便作为我们进⼀步理解现代计算机⼯作原理的基⽯。
算数单元,负责计算机⾥的所有数字操作,⽐如四则运算,当然它能做的远远不⽌这些。接下来我们会带着⼤家实现⼀个 8 位(bits)的加法器(adder)来,以演⽰整个过程,其他的运算器就不再详细讲解了。
⾄此,⼀个 8 位(bits) 加法器就被我们从⽆到有制作了出来。算术单元⽀持的操作当然远不⽌这些,通过继续组合逻辑⻔,算数单元可以做到加减乘除甚⾄更多的算术运算,但⼀个加法器作为演⽰已经⾜够了。实际上,乘法器和除法器的制作难度是要⾼于加、减法器的,有兴趣的同学可以尝试做更多的了解。
逻辑单元主要⽤来进⾏逻辑操作,最基本的操作就是 与、或、⾮操作,但不只是⼀位(bit)数的⽐较。
经过我们的努⼒,通过基本的逻辑⻔电路,我们⼀步步地做出了⼀个 8 位(bits) ALU,甚⾄⽐ Intel 74181 还要强⼤,Intel 74181 只是⼀个 4 位(bits) ALU。当然现代的计算机中的 ALU 部件⾮常强⼤,复杂度远远超过了我们的想象,32 位 甚⾄ 64 位基本已经普及全球了。但⽆论如何,再复杂的 ALU 也是芯⽚⼯程师像我们这样,⼀层⼜⼀层,⼀步⼜⼀步地将其抽象出来的。ALU 是第⼀次将⼈类历史上的数学和逻辑学学科有机地结合起来,可以视为⼈类智慧发展的现代巅峰。
光有 ALU 还是远远不够的,我们⽆法为 ALU 提供存储的部件,所以接来下,我们利⽤⻔电路简单说明下存储的制作。注意,虽然图中没有明显的表⽰出来,但这些存储都是要求必须保持通电状态的,也就是这些存储都是易失的(volatile)。
中间我们隐藏了⼀些实现细节,最后的效果就是:使能线置位时,输⼊为 1,保存 1;输⼊为 0,保存 0。使能线不置位时,则写⼊⽆效。我们可以利⽤⻔锁,构建我们需要的寄存器和内存。
内存的构建要⽐这个复杂⼀点,但基本原理⼀致。如此构建的内存被称为 RAM(Random Access Memory),可以⽀持 O(1) 时间复杂度访问任意位置的数据,这也就是我们数组下标访问操作是 O(1) 的硬件⽀持。
我们现在有 ALU、存储了,但这还是不⾜以让我们的计算机⼯作起来,我们需要有⼀个部件来指挥 ALU 进⾏何种的运算,⽽这个部件就是控制单元(CU)。
⾸先,我们先介绍下我们需要到的指令(instruction)。
所谓指令,即指 CPU 进⾏⼯作的命令,主要有操作码 + 被操作数组成。
其中操作码⽤来表⽰要做什么动作,被操作数是本条指令要操作的数据,可能是内存地址,也可能是寄存器编号等。
指令本⾝也是⼀个数字,⽤⼆进制形式保存在内存的某个区域中
上面这一段的指令,其实就是内存中的一段数据
第一步:
第二步:
第三步:
第四部:
再往下就是0地址了,说明指令已经执行完了。
1、CPU要执行的指令,是在内存中的(冯诺依曼体系结构,基本设定,执行单元(CPU)和存储单元(内存)是分开的,让执行单元和存储单元解耦合)
2、CPU要想执行指令,就需要先取指令,再解析指令,然后才能执行指令。
3、取指令需要从内存中读取指令到CPU的寄存器中,取指令的操作,其实是非常耗时的(读取内存操作相对于CPU执行计算,开销要大很多)。因此CPU中通过“缓存”、“流水线”等技术,来优化这里的效率。
4、CPU解析指令的时候,需要用到“指令表”,不同架构的CPU支持的指令表不同(x86和arm等都是不同的),指令表细节,已经写死到CPU中了,CPU是可以很容易识别的。
5、指令在执行过程中,可能会带有一些操作数,不同指令、操作数的个数含义都有所不同。
6、CPU重要的参数,主频:主频表示的含义,近似看成是一秒钟以内,CPU能够执行的指令个数。
操作系统是一个软件,有代码构成的程序
主要职责:
1、管理各种硬件设备
2、给其他软件提供稳定的运行环境
上面这两种职责类似抽象、封装。我们的电脑有很多硬件,如显示器、鼠标、内存、硬盘等等,
这些硬件的生产厂商都不同,所提供的的API也会不同,那么一个电脑是怎么兼容那么多不同的硬件设备呢?很显然,是Windows操作系统,统一管理这么多硬件设备,给软件统一API。
进程就是操作系统提供的一种软件资源,我们现在的电脑所用的就是多任务操作系统,可以同时运行多个任务,如:edge,QQ,IDEA等等,而单任务操作系统一次只能运行一个任务,如:老年机。
1、先描述,用类 / 结构体这样的的方式,把实体属性表示出来,我们给表示进程的结构体统称为PCB。
2、再组织,用一定的数据结构,把这些结构体给组织起来,在Linux中,使用链表的这种数据结构将这些结构体给组织起来。
PCB是一个非常庞大的结构体(上百个属性),我们要怎么怎么区分这么多的属性呢?
引用pid,进行身份标识,用不同的整数,代表不同的进程,这些整数都是不重复的,用来区分电脑上那么多不同的进程,系统也会保证,每个进程的pid时唯一的。
比如我们在任务管理器结束一个任务,就要在任务管理器中选取到这个pid,然后调用系统api,把pid参数传进去,就能把这个后台杀死。
整个系统中,有些人的电脑的内存是16G的或者其他大小的内存,那么我们内存这么多,16G都可以给我们随便调用的吗?显然不是,就好比去旅馆开房,我们要先订房,交钱才能进到指定的房间,但是如果我们直接强行进入某个房间呢,显然是不合法的。内存的调用也是如此,每个进程,都必须自己申请一块内存,申请了这块内存,进程才能使用。
而内存指针,就是用来描述:某些进程能使用哪些内存。内存指针,也是描述某些进程的使用情况。
文件描述符表,描述了这个进程,所涉及的硬盘相关资源。一个进程想要操作文件,需要先“打开文件”,而打开文件,就是让进程在文件描述符表中分配一个表项(构造一个结构体),表示这个文件的相关信息。
上面的都是内存、硬盘在pcb中的体现,那么在CPU中的体现如何呢?
一个进程消耗CPU资源是啥意思?比如CPU是一个舞台,要执行的指令就是演员,但是同一时刻,一个舞台只能给一个演员表演,CPU可能是单核的,也可能是多核的,这时就涉及到分时复用(并发)。
单核的cpu:是先处理进程1完,再处理进程2....,依次往后推的,但是处理这些进程的过程是很快的,我们人脑的反应没那么快,只要电脑切换的足够快,我们人感知不到,我们就可以认为同一时刻,在人眼看来就是多个任务 / 进程 “同时进行”。这个就是并发。
多核CPU,也就意味着有多个舞台,多个演员可以在舞台上表演,也就是多个进程可以同时执行,只不过是在不同的核心上,这个就是并行,同时也在发送着并发,因为每个核心都在快速的切换不同的进程。
当代计算机执行的过程,是并行和并发同时在发生的,对此,往往就把“并行和并发”统称为并发。
描述某个进程,是否能够在CPU上执行,有的时候会不能执行,比如说Scanner,这个要等用户输入完内容,才能执行下一个指令,而状态分又可以细分,如下。
就绪状态:
随时准备好去CPU上执行,操作系统,一打招呼,就立马执行这个指令。
阻塞状态:
这个进程,当前不方便去CPU上执行,不应该去调度它,(比如,进程在等待IO,来自控制台的输入/输出)
多个进程在等待系统调度,多个进程的调度会有先后关系,不那么平均,比如你在玩cf,打开了cf,同时qq在后台挂着,这时cf的优先级就比qq高,先玩游戏,玩完后才看qq是否有消息。
针对每个进程,占据多少CPU的时间,进行一个统计,会根据这个统计结果来进一步调整调度策略,因此就需要在下一个轮次进行调整,确保每个进程都不至于出现完全捞不着CPU的情况。
上下文其实就是一种记录数据和恢复数据的形式,是支撑进程调度的重要属性。
类似游戏中的存档和读档。
存档:就是进程中得出的某些中间结果,把这个中间结果放在内存的某一个地方上。
读档:等进程需要某个中间结果数据的时候,就从内存中调用这个数据,恢复到进程中。
保存上下文:就是把cpu关键寄存器上的数据,保存到内存中。
恢复上下文:就是把保存在内存中的一些关键数据,加载到CPU上的对应寄存器中
核心结论:每个进程都是相互独立的,互不干扰的。具有“独立性”
如果一个进程崩溃了,也影响到了其他进程崩溃,这种情况,用户的体验是很差的。所以一般情况下,A进程是不能直接访问B进程的内存。
虽然进程具有“独立性”,但是进程间的通信和“独立性”是不矛盾的。
当一个任务需要多个进程来协同配合完成,系统就会提供一个公共空间,让不同的进程在这个公共空间进行数据交互。