JavaEE初阶系列 -开头篇:计算机是如何工作的(为下一篇的线程做铺垫)

文章目录

  • 前言
  • 计算机的发展史
  • 冯诺依曼体系
    • CPU 中央处理器: 进行算术运算和逻辑判断.
  • CPU 基本工作流程
    • 逻辑门
    • 门电路(Gate Circuit) – 模电数电知识
      • 1、与门:可以针对两个二进制数(0 / 1)进行与运算
      • 2、或门:与门:可以针对两个二进制数(0 / 1)进行或运算
      • 3、非门:可以对一个二进制数(0 / 1)进行取反,.就是我们编程中的 按位取反。
      • 基于上述的基础门电路,能构造出一个复杂的门电路。异或门电路
      • 算术逻辑单元 ALU(Arithmetic & Logic Unit)
        • 算术单元(Arithmetic Unit)
          • 半加器 – Half Adder
          • 全加器
          • 8 位 数加法器
        • 小结
  • CPU 里面除了运算器之外,还有控制单元和寄存器。
    • 寄存器
    • 控制单元(CU)
      • 指令 (Instruction)
        • 指令是如何执行的/li>
          • 指令表(Instruction Table) / 构造手册
          • 拓展:如何计算 两个数相加/li>
  • 题外话
  • 操作系统
    • 操作系统的作用是什么/li>
    • 什么是进程/任务(Process/Task) – 上面你们随便看看,但是这里是重点(与线程有关)
    • 操作系统是如何管理进程的/li>
      • 1、先描述一个进程。
      • 2、再组织若干个进程
      • 详解
        • 了解 PCB中的一些属性
          • 1、pid(进程id) – 进程的身份标识
          • 2、内存指针
          • 3、文件描述符表
            • 细节拓展
        • 小结:如何让一个进程正常工作
        • 上面的属性是一些基础的属性,接下来的一组属性,主要是为了能够实现进程调度。
          • 4、状态
          • 5、优先级
          • 6、记账信息
          • 7、上下文
      • 拓展
  • 重点部分总结
    • 1、 进程是什么/li>
    • 2、进程是怎么管理的/li>
    • 3、 进程的 PCB 里 都有什么/li>
    • 4、进程的调度是怎么进行/li>
    • 5、进程的独立性是什么/li>
    • 6、进程之间,如何通信/li>

前言

我们这片文章,只讲一些偏重要的部分。另外注意不需要背,你就当开阔一下知识面积。

计算机的发展史

计算的需求在人类的历史中是广泛存在的,发展大体经历了从一般计算工具到机械计算机到目前的电子计算机的发展历程

之前博主讲的冯诺依曼体系,主要是针对存储器,着重讲的内存和外存。
访问速度:内存块,外存慢。
造价:内存高,外存第
存储空间:内存小,外存大
持久化存储;内存断电后,数据就没了;外存掉电后,数据依旧在。
除了存储器,电脑最重要的部件就是CPU了、
下面我们讲讲CPU。


/p>

CPU 中央处理器: 进行算术运算和逻辑判断.


/p>

CPU 基本工作流程

接下来,我们用一个从无到有的过程,一步步搭建一个 CPU 出来,希望大家可以借助这个过程,理解CPU、内存等计算机主要部件的工作原理。【当然并不是真的去设计一个CPU,值简单了解一下】


/p>

逻辑门

电子开关 —— 机械继电器(Mechanical Relay)


/p>

2、或门:与门:可以针对两个二进制数(0 / 1)进行或运算

1 1 = 1
1 0 = 1
0 1 = 1
0 0 = 0
有 1 出 1,全 0 出 0


/p>

基于上述的基础门电路,能构造出一个复杂的门电路。异或门电路


/p>

算术单元(Arithmetic Unit)

算数单元,负责计算机里的所有数字操作,比如四则运算,当然它能做的远远不止这些。接下来我们会带着大家实现一个 8 位(bits)的加法器(adder)来,简单演示整个过程

/p>

半加器 – Half Adder

是针对两个比特位,进行加法运算


/p>

8 位 数加法器

A 和 B 是 2个bit 的 数字
A0 这个数字就是 第 0 位(最低位,也就是最右边)
然后 A1 是 第 1位,最右边倒数第二个、
A2、A3…依次类推
B 也是同样的。

示例2:指令(机器语言) : 0001 1111

示例4:指令(机器语言) :1000 0100


/p>

题外话

虽然我们用的都是高级语言,汇编语言几乎不会用到、
但是在一些特殊领域上,就需要用到汇编,就需要理解机器指令。
比如:

1、游戏领域【外挂】

外挂是一个单独的程序,对于一个游戏来说,源代码是不会开源的。
虽然没有原码,但是可以有执行程序(后缀 exe 文件),这里面其实就是二进制的机器指令。
这些文件里面有特定的结构(Windows:PE结构,Linux: ELF)
这些结构,其中有个部分叫做代码,包含了程序涉及到一些逻辑。(二进制指令)
我们就可以通过研究这里的机器指令,找到一些关键逻辑。
比如:吃鸡的锁血外挂,就是找到中弹扣血逻辑。
修改一些机器指令的条件判定加上算术运算,或者把扣血量设置为0的操作。
其实就可以达到实现外挂的逻辑。
但是需要你 非常理解 汇编语言

2、安全领域(病毒)
外挂只是针对游戏病毒进行逆向,而病毒是针对系统的逆向。
两者的本质是一样的。


/p>

操作系统

首先,大家要知道 操作系统是一个“软件”。
这是计算机上最重要,也最最复杂的软件之一。
比如:
Windows、Linux、mac、Android、ios、openwt…


/p>

操作系统的作用是什么/h2>

”操作系统作用主要就是管理,操作系统就是一个搞 “管理的软件
1、对下,要管理好各种硬件设备
2、对上、要给各种软件提供一个稳定的运行环境。
由此不难看出:操作系统 相当于 在 软件和硬件之间 建立了一座“桥梁”。
这个时候,我们的软件和硬件就可以更好的进行交互,更好的进行相互配合,更好的来完成一些共同的工作。


/p>

2、内存指针

内存指针:指明了这个进程执行的代码在内存的位置,以及 这个进程执行中依赖的数据都在哪里。
首先,我们要明确一件事:当 运行一个 exe 文件,此时操作系统就会把这个 exe 加载到 内存中,变成进程。(此时的进程 就和 这块内存 是 绑定在一起的,是相关联的)
其次,此时我们的内存就包含了很多东西,因为exe文件是加载到 内存中,所以 exe文件里有什么,这块内存中就有什么。
在 这个 exe文件中,就包含这 进程要执行的二进制指令。(通过编译器生成的)
同时,除了指令之外,还有一些重要的数据。
而 这些指令 与 数据 都会存入到内存中,并且是放在内存的不同区域里面。
这个时候,我们就需要进程知道 当前我们的指令是在哪一个内存区域中,要使用的数据 又存储在内存的哪一块区域中。
通过 内存指针,进程就能找到我们当前执行的指令有哪些,以及数据有哪些。


/p>

3、文件描述符表

我们的程序运行过程中,经常要和文件“打交道”。(文件是硬盘上的)
我们C语言中就讲过文件操作,java里面也有相关的文件操作,后面也会讲到。
不管是那种语言,这都是属于文件操作。既然是操作文件,那么本质上就是在操作键盘。
br> 操作文件的步骤:
1、打开文件
2、读 / 写文件
3、关闭文件
注意,进程每一次打开一个文件,就会在文件描述符表上多增加一项。
这个文件描述符表就可以视为是一个数组,里面的每一个元素 又是一个结构体。每个结构体都对应着一个文件的相关信息。
我们的一个进程运行的过程中,要打开那些文件,和那些文件进行交互,都会被记入到 文件描述符表中数组的里面。


/p>

细节拓展

假设我们的代码没有什么打开文件的操作,就是一个打印语句 “hello Word” 的情况下,还是需要 文件描述符表的!!
一个进程只要启动,不管你代码中是否写了 打开 / 操作 文件的代码,系统都会默认打开三个文件:标准输入(System,in),标准输出(System.out),标准错误(System.err).
对应的 文件描述符表中 会创建三个表项,标准输入、标准输出、标准错误对应的下标:0、1、2。
这个文件描述符表的下标,就被称为文件描述符。


/p>

小结:如何让一个进程正常工作

看到这里,我们如果想让一个进程正常进行工作,势必会给它分配一些系统资源。
1、内存(加载exe文件到内存中,肯定是需要占用一定内存的)
2、硬盘(操作 文件)
3、CPU(执行进程上的指令)
大家一定要明确:要想让进程正常工作,操作系统必须在硬件上给这个进程 提供 一些必要的硬件资源的支持。这样才能能够保障进程的基本工作,才能够保障我们来完成这个进程需要的一些工作任务。


/p>

上面的属性是一些基础的属性,接下来的一组属性,主要是为了能够实现进程调度。

理解什么是进程调度,是我们 理解进程管理的一个重要话题。
要想理解什么是进程调度,首先我们要知道:现在的操作系统 一般都是 多任务操作系统。
多任务操作系统:一个系统同一时间,执行了很多的任务。
与之相对的就是 单任务操作系统:同一时间,只能执行了一个任务/进程。
对于 单任务操作系统,是不需要考虑调度的。
因为它同一时刻,只执行一个进程。
br> 再看看我的电脑,它是Windows系统,就是多任务的操作系统。
同一时间有很多进程都在运行 。

JavaEE初阶系列 -开头篇:计算机是如何工作的(为下一篇的线程做铺垫)
但是呢,这里存储在一个很重要的问题:就是我的系统上任务的数量(进程的数量),有几百个(我看了我的电脑大概200个,前面还说少了)。
但是我的电脑 CPU 核数 就那么几个(4核),这么多的任务是怎么一起执行的呢br> 这件事请就是所谓的“进程调度”。
所谓的“进程调度”:就是让有限的核心,能够同时执行很多很多的任务。

关于 让有限的核心能够同时执行很多很多的任务。
这里我们需要进一步的理解一组知识点:并发 和 并行。(在MySQL中讲事务的隔离性的时候,浅显的讲了一下)
br> 所谓的并行 和 并发,
并行:从微观上来看,两个CPU核心,同时执行两个任务的代码。
br> 并发:从微观上来看。一格CPU 核心,先执行一会 任务1,在执行一会 任务2…最后再执行 任务1。
就是执行一圈又回来了。相当于每一个任务都执行一小段逻辑,立刻切换到下一个任务,再执行一小段逻辑,依次进行快速切换,只要切换的够快,那么从宏观上看起来,就好像这么多任务在同时执行一样。
br> 从宏观出发:并行 和 并发 都是 同时执行两个任务。
从微观出发:
并行:多个核心 执行 多个任务
并发:单个核心 按照串行的方式 执行多个任务,但是只要它切换的足够快,从宏观来看就好像是多个任务在同时执行一样。

其实从宏观出发:
并行 和 并发 这两件事,只是在微观上有区别,在宏观上没有区别,也区分不了。
br> 微观上的区别 都是操作系统自行调度的结果。
就比如说:我的电脑现在是 4 核,同时跑 20 个 任务。
其实这些任务中,有些是并行的关系,有些是并发的关系。
并且 可能 任务 A 和 任务 B 上一秒是并行的关系,下一秒就成并发的关系。(两者的关系是不稳定的,是会改变的)
这些情况都是微观上操作系统在控制的。
在宏观上是看不出来是 并发,还是并行的关系!

正是因为 在 宏观上区分不了并发和并行,所以我们在写代码的时候也不去具体区分这两个词。
实际上通常使用 “并发” 这个词,来代指 并行 和 并发。
咱们只是在研究操作系统的进程调度这个话题上,稍作区分。(就是讲一下)
但是在其他场景中,基本都是使用 “并发” 作为一个统称 来代替的。
br> 相信大家都听说过这样的一个词:并发编程
此处的并发,就是包含了 “并发” 和 “并行”的统称。

讲到这里,其实所谓 进程调度 :让有限的CPU核数,去执行更多的任务。
关键就在于它切换的速度。其实它切换的速度是非常快的!
我电脑主频就是 2.8GHz,一秒可以执行28亿条件指令。(细品)
所以我们人是感受不到 进程之间 是否在切换的。


/p>

4、状态

这个状态,就描述了当前这个进程接下来该怎么去调度。
我们只讲Linux中的种状态 :
1、就绪状态
2、阻塞状态 / 睡眠状态,暂时不可以去CPU 上执行。
Linux中的进程状态还有很多其他的。。。

正常情况下,这A、B、C 三个人随叫随到。【就绪状态】
假设:
A 要要出差一个月,显然A是不能随叫随到的。【A 处于一个 阻塞状态 / 睡眠状态】
对于处于这种状态的进程,就暂时不进行调度。(不将A排入到时间表上)


/p>

5、优先级

当我们有很多任务的时候:先给谁分配时间,后给谁分配时间;以及给谁分的多,给谁分的少。

任务之间,有的任务优先级很高,有的优先级很低。
针对 A、B、C三个人,最喜欢 B,其次是 C,最后是A。
我在安排时间表的时候,就会优先给 B 排,其次给C,最后给A。
周一 至 周三,都给B在一起。
周四 至 周五, 和 C 在一起
周六,和 A 在一起
周日:给自己放假
关于这一点,操作系统 给 进程 分配时间也是类似的。
有的进程优先级高,有的进程优先级低。
它们所受到的待遇是不同的。


/p>

6、记账信息

统计了每个进程,都分别被执行了多久,分别都执行了那些指令。
分别都排队等了多久了…
记账信息 主要是给 “进程调度” 提供指导依据。

如果长此以往,和 A 在一起的时间太少了, A对我的好感度就会降低。
这个时候,她舔的也不卖力了。我感觉我快要失去这个“钱包”了。
这个时候可以根据之前本子上安排的这个时间,就能发现给A安排的时间太少了。
接下来就适当的给她一点甜头。(头上长出犄角)
唤醒A的好感度。
放在进程中,就是不能对某个进程太冷落,导致它一直占用不了CPU。
所以我们就可以根据记账信息来灵活调整调整我们的一个分配策略。
故:得先记账。先去统计好这里面每个进程当前所吃的资源,然后再根据这里面的统计结果,来去对那些分配特别少,特别不均衡的进程,再去做出一些补偿。


/p>

7、上下文

表示 上次进程被调度出 CPU 的时候,当时程序的执行状态。
下次 进程 入 CPU的时候,就可以恢复之前的状态,然后继续往下执行。
换个经典的说法:上下文的作用就是 存档 和 读档。
用单机游戏来表示的话:存档存储的游戏信息,就称为“上下文”。
br> 当进程 被调出 CPU 之前,要先把 CPU中所有的寄存器中的数据都给保存到内存中【PCB 的 上下文字段中】 想相当于存档了。
下次进程再被调度上CPU的时候,就可以从刚才的内存中 来 恢复 这些数据 到 寄存器中。就相当于读档。

某一天,A给我说,下个月带我前言夏威夷度假。
让我准备准备,
紧接着的下一天,B 和 我说,下周,她外婆过生日,叫我准备点礼物。
&ensp
过几天后,
A 和我 提起度假的事,问我准备的怎么样br> 我说 :“礼物买好了。”
A 说 :“礼物,什么礼物
【这不就穿帮了嘛!】
A 说 的 度假准备好了吗br> 而 我们回答的却是 B 说的 礼物准备好了。
很显然 A 和 B 的 准备 是 截然不同的。
怎么区分开br> 很简单,用小本本记着。(PCB 的上下文字段)
因此,我作为时间管理大师 是有 记录日记的好习惯。
于是,我就把每次约会的重要信息记录下来。
然后,下次再和她们在见面的时候,都能对上 ,哪怕时间长一点也没有关系。
通过这样的方式,我们就可以记录上次约会所达成的状态,下次再约会的时候,就可以接着上回继续往下进行了。
这样的操作就被称为 “上下文”。


/p>

拓展

进程的调度,其实就是 操作系统

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年2月18日
下一篇 2022年2月19日

相关推荐