计算机是如何工作的

发展史

  • Java 最初诞生的时候,适用于“嵌入式开发”

  • 后来给网页网页开发逻辑(Java 在进行前端开发),迎来第一波巅峰

  • 后来被微软打压后寻出路,开始做服务器开发(后端开发)和嵌入式开发,并推出三个版本

    • Java 标准版:J2SE——>JavaSE

    • Java 企业版:J2EE——>JavaEE

      • 服务器开发这条路挺进,当年这条路上的王是 PHP
      • Java仿照 PHP 搞了一套 JSP,当上了二哥
    • Java 精简版:J2ME——>JavaME

      • 嵌入式开发这条路挺进
      • 手机开始崛起(功能机),例如:诺基亚、摩托罗拉…
      • 可以安装第三方程序—>以 JavaME 的方式来开发的
        以前手机游戏加载 logo 就是 Java 的咖啡杯
  • 随后 Java 重回巅峰

  • 但随着时代的的进步,新的风暴出现

    • 后端领域:以 PHP 为首的后端开发技术,随着网站规模变大(2010 年后),变得难以适应

    • 移动领域:

      • 2007 年,乔布斯发布了第一代 iPhone,载入史册,标志着移动互联网时代开启,智能手机的时代开启
      • 2011-2012 年左右,iPhone 4 最有影响力的版本出现,功能机遭遇滑铁卢,若基亚一夜破产
      • 导致 JavaME 这套技术体系,也被雪藏
  • 之后随后继续寻找出了,第三次达到巅峰,两条腿均成为大哥,Java 一跃冲到编程语言的榜首,霸榜好多年

    • 后端领域:Java 开始逐渐摒弃 JSP 这一套技术,并且 Java 社区中诞生了新的王者,Spring,给 Java 带来了新的春天

      • Spring 是一组以 Spring 为首的框架,提供了后端开发的全套解决方案,非常好的适应了大规模网站的开发
      • 在 Spring 的加持之下,Java 逐渐反超了 PHP 成为后端开发的老大
    • 移动端开发:JavaME 倒了,新的王者 Android 诞生了(背后是 Google)

      • 安卓诞生的时候,谷歌当时准备想以 Python 作为安卓开发的语言,但 Python 之父和谷歌闹了矛盾,导致谷歌一怒之下选择了 Java 作为安卓的开发语言
      • 并且之前做手机的时候是以 Java 作为开发语言的,谷歌选择 Java 就业能很好地将之前那批搞 JavaME 的人诏安过来。
      • 这样安卓上的开发者多了,应用程序多了,吸引到更多用户<==>吸引到更多开发者正向循环
      • 因此,Java 也成为移动开发端的老大
  • 到了 2020 年之后,Java 又面临着新的挑战

    • 后端开发:Java 迎来最大的挑战者“Golang”,作者是肯汤姆逊(C 语言之父)

      • Java 的风格太规范,一板一眼,使得 Java 开发程序经常“模式套模式,框架罗框架”,开发程序显得很笨重,开发大规模程序是有优势的,但开发中小规模程序,反而成了制约
      • 而 Golang 风格简单直接,核心语法都是和 C 语言一样,非常精简。Go 也抓住了后端开发的新的契机:分布式—>微服务化
        • 微服务化:因为一个网站后端越来越重,越来越复杂。与其一个程序完成所有问题,不如搞很多程序相互配合,每个程序都可以变得更简单,更单一…
      • 目前 Go 在当前业界的影响力是非常大的,尤其是国内,很多恭喜都开始投入到 Go 这个圈子了
    • 移动端开发:Java 的老板 Oracle 由于眼馋安卓的收益,直接把谷歌告了,因为其用了 Java 进行开发。这导致谷歌感觉很膈应人,之后开始主推 Kotlin 作为安卓的开发语言

      • Kotlin 是 JetBrains 推出的(谷歌也是它的股东)。Kotlin 也是把编程语言编译成兼容 JVM 的字节码,使 Kotlin 可以白嫖 Java 的生态
      • 其他人看了都说好,Scala、groove… 这几个语言也开始白嫖 Java 生态

冯诺依曼体系结构

  • 计算机最早是运用于军事的

    • 埃尼阿克-第一台计算机,194x ,冯诺依曼大佬参与研发,用来计算导弹轨迹
  • 后来冯大佬带队,开发“通用计算机”。后来计算机成了民用重要的支撑

  • 计算机内部大同小异,当前计算机内部构造整体规则就是冯大佬提出的,冯诺依曼体系结构

  • 冯诺依曼体系结构

    • 组成
      image.png|568
      • CPU(看 CPU 是否 nb,就看核心数数量和频率高低
        人类科技的巅峰之作,和氢弹齐名

        • 计算机最核心部分

        • 中央处理单元,完成算术运算和逻辑判断

        • CPU 主流架构

          • x86 / x 64 架构

            • 给桌面端 / 服务器使用
            • AMD 的霄龙(EYPC)
          • arm 架构

            • 给移动端 / 嵌入式使用
              • 性能更弱,但功耗低,续航久
          • RISC-Ⅴ

            • 一套开源的 CPU 指令架构,在国内比较落后,奋起直追
        • CPU 核心参数

          • 核心数
            image.png|251

            • 里面有多少个方框就有多少个核心(16 个)
              • 最早的 CPU 都是单核心(CPU 里只有一个人干活),当时 CPU 往更快的速度去卷。需要让 CPU 集成程度更高,包含更多的运算单元才能算得快,因此每个单元体积就得小

                • 体积过小,经典力学就失效了,进入到量子力学领域—>工艺上的挑战越来越大
              • 既然向下不好卷,就开始横向发展,英特尔率先开始发展多核

                • 发展到四核后,英特尔希望每个核心都能做两个核心的活,就出来了一个“超线程技术”,例如四核八线程八核十六线程
                • 后来 CPU 核心数越来越多,在服务器领域已经有 128 核 256 线程的 CPU
                • 现在英特尔开始搞没用的大小核机制;正常一个 CPU 核心顶俩,但是英特尔区分大小核,大核顶俩,小核顶一个。为了骗跑分
              • 目前 Intel 和 AMD 过不了一招,被按着打

            • CPU 核心对程序员影响是非常大的,对我们来说,现在一个很重要的任务就是:我们写的程序要能充分地利用好多核 CPU 的资源
              • 并发编程:程序员在代码中把任务拆成多个,使用不同的核心分别执行(多线程章节细说
              • Golang 在这方面有天然优势
          • 频率
            一秒执行多少个指令,随着任务量进行动态调整
            image.png|339

            • 基准速度:正常工作下的频率(一秒运算 32 亿次,就是处理 32 个指令
              速度:实时频率,频率越快,耗电越高,发热更多
              • 防止发热过多烧掉 CPU,计算机都有“功耗墙”:当 CPU 温度达到一定阈值后,自动降频,
              • C/Java 语言,编写程序写的语言,最终都要被翻译成“CPU 上执行的二进制指令”,这里的指令就是指 CPU 干活,完成任务的基本单位
                (将一件事拆分成很多步骤,拆到极限后的每个步骤就是指令
                • 指令也就是机器语言(二进制) 或者是汇编语言(单词符号),它们俩是一一对应的,每有一条机器指令,就有一条对应的汇编语言
                • 不同的 CPU,支持的指令是不同的,这样就会有兼容性问题:x86 上的指令和 arm 的指令是不能通用的
        • 寄存器

          • CPU 在进行运算的时候,要先把数据存到 CPU 的寄存器中
          • 储存空间比内存更小,速度比内存更快(好几个数量级),成本比内存更高,断电后数据会丢失
          • 寄存器空间太小,往往只是几 kb 是,因此 CPU 在计算的时候就需要反复地从内存加载数据,效率比较有影响(内存读的速度相对寄存器来说就是弟弟,拖后腿了)。所以现代 CPU 引入了缓存
            • 现代缓存往往是三级缓存结构(L1,L2,L3)
              image.png|180

              • L1:空间最小,速度最快
                L2:空间最大,速度最慢(也比内存快很多)
            • 某个内存的数据经常使用,寄存器又存不下,就可以放到缓存中

              • 数据使用频率高,就往 L1 上放,没那么高就放 L3,中间的就放 L2
            • 对于 Java 程序员来说,开发程序不会把寄存器和缓存区分得这么细,通常会把他们视为一个整体

            • 缓存如果大了,对于有些场景中性能提升是非常大的

      • 存储器

        • 内存
          存储空间小,访问速度快,成本高,掉电后数据丢失
        • 外存
          储存空间小,访问速度慢,成本低,掉电后数据仍在
          • 硬盘
          • 软盘
          • 光盘
          • U 盘
      • 输入设备

      • 输出设备


CPU 执行指令过程

  • CPU 能执行哪些指令,可以认为是 CPU 最初设计的时候就已经确定好了,存在一个“表格”,描述了都有哪些指令
    image.png|650
    • 这是一个简化版本,真实的 CPU 指令表,比这复杂很多很多

      • 此处假设每个指令只有 8 bit,实际上一个指令更长(64 位机器的指令可以有 64 位)
      • RAM 是随机存取存储器(Random Access Memory),也叫内存
      • CPU 寄存器很少,所以每个都有专门的名字(表中的是虚构的)
      • 8 bit 的指令分为两部分:
        • 前 4 bit:操作码(opcode)表示指令是干啥的
        • 后 4 bit:操作数(类似于函数的参数)
          内存很大,可以把它想象成一个大的宿舍楼,这个操作数就是找到房间的门牌号
    • CPU 的基本工作流程

      • C 语言写好的程序,先编译成可执行文件.exe包含了这个程序运行时要执行的指令和依赖的数据),进行运行的时候,操作系统会把 exe 加载到内存中

      • CPU 中有一个特殊的寄存器叫“程序计数器”,保存了接下来要从哪个内存位置来执行指令。在 exe 加载到内存后,程序计数器保存的位置就被系统自动设置好了·

        • image.png|100
          • 此处就可认为,程序计数器被设为 0 了,接下来从 0 号地址开始执行指令
          • 随着指令的执行,这里的值也会随着更新。默认情况下是+1 自增过程(顺序执行),若遇到“跳转类语句”(if、while、for、函数调用…)会被设为其他值
      • 执行指令的三个重要阶段

        1. 取指令,CPU 从内存中读取指令内容到 CPU 内部(有专门的寄存器来保存读取到的指令)
          • 此时程序计数器为 0,执行地址为 0 的指令
            image.png
        2. 解析指令,识别出这个指令是干啥的,以及对应的功能和操作数
          • 前四位 0010 是操作码,看指令表可知,这是 LOAD A 指令:把后面四位 1110(换成十进制是 14)操作数这个地址的数据,读取到寄存器 A 中
        3. 执行指令
          • 把 14 地址的内存数据读取出来,放到寄存器 A 中
            image.png
        4. 第一条语句执行完毕,程序计数器中的值自动被系统++,从 0—>1
        5. 此时程序计数器为 1,执行地址为 1 的指令
        6. 重复 1、2、3 操作,直到取到的数据为 00000000,程序执行结束

[!NOTE] 游戏外挂(射击类重灾区)

  • 游戏程序也是 exe,游戏逻辑的指令,也是包含在 exe 文件中,加载到内存中的。
  • 有些外挂开发人员分析内存中的指令,找到一些特定的逻辑,进行修改。
  • 比如:发现某几个逻辑是控制掉血的,也是就可以写另一个程序,动态修改掉游戏程序对应内存空间里的指令,变成中弹不掉血
  • 现在写外挂的主要难度不在于分析指令,而是在于如何绕过游戏公司的“反外挂机制”(腾讯TP)

[!info] “打热补丁

  • 对于 Java 程序员来说,给程序“打热补丁”是一个比较典型的指令级开发场景
  • 比如,在做一个服务器开发的时候,这个服务器非常重要,不能重启,但发现服务器存在严重 bug,此时就可以考虑“打热补丁”
  • 写的程序的指令是在内存中的,对应的有 bug 的代码,也是其中一段指令,找到有 bug 的代码指令,直接把这里的指令修改成没有 bug 的版本,或者在这个指令前加上跳转指令,让有 bug 的指令不去执行,而是去执行新增的一个正确的指令

操作系统

  • 下面是一些主流的操作系统,他们之间都是不兼容的

    1. Windows
    2. Linux
    3. Max OS
    4. Android
      • 内核是基于 Linux 开发的,但经过多年迭代,差异很大了
      • 最主流的系统
      • 鸿蒙属于是安卓套壳,也是属于 Android 阵营
    5. IOS
      • 和 Mac OS 是两套系统
    6. 其他小众系统
  • 一个操作系统要做很多事情

    • 最重要的是“管理”
      image.png|483
      1. 管理不同的硬件设备
        • 计算机能接入很多设备,例如,扫码枪、医疗设备、B超超声波…
      2. 给软件提供一个稳定的运行环境
        • 现代的操作系统都是要同时运行很多程序,我们希望这些程序之间不会相互干扰,某个程序出 bug 不会影响到其他的程序
        • 操作系统会给应用程序提供 API,让应用程序调用,完成不同的操作
          • 比如在 Java 中打印一个 println("hello world")
            • println 是一个 Java 标准库中提供的函数,在 JVM 中,为了实现 println,就会调用操作系统提供的 API 执行(Linux 对应的系统 API 叫做 write)
            • 调用系统 API,程序就会进入到系统内核执行,此时系统就会操作对应的硬件设备,来完成打印操作
  • 操作系统的组成
    主流系统都是用 C/C++实现的

    • 配套的应用程序
    • 内核
      • 操作系统核心功能区
      • 他的核心功能就是上面的管理不同硬件设备给软件提供一个稳定的运行环境
      • 里面要包含的功能非常多,其中有一个功能和我们日常开发息息相关,“进程管理”(单线程)
        • 进程管理(进程process / 任务 task)—>正在运行的应用程序
          image.png|235
          • 进程(单线程)

            • 一个应用程序有两种状态
              • 没有运行的时候,是一个 exe 文件,躺在硬盘上
              • 运行的时候,exe 就会被加载到内存中,并且 CPU 执行里面的指令了,就叫“进程
            • 这些进程,操作系统都要执行。执行进程里面的指令,是需要硬件资源
              image.png|281
            • 进程是操作系统进行资源分配的基本单位
          • 进程管理
            由于系统上进程较多,才需要管理

            • 描述

              • 通过结构体/类,把进程的各种属性表示出来
            • 组织

              • 通过一些数据结构,把上面的结构体串起来,并进一步的进行各种增删改查
            • 例子:

              • 对于 Linux 操作系统来说,使用称为“PCB(进程控制块)“ 这样的结构体来描述进程信息。
                简单认为,是通过链表的方式,把上述多个 PCB 串到了一起。
                创建新的进程(双击 exe,运行起程序),就相当于创建了一个 PCB 结构体,并且插入到链表中。
                销毁进程,就是把 PCB 从链表上删掉,并且释放这个 PCB 结构体。
                查看进程列表,就是在遍历这个链表,依次显示出对应的信息。
            • PCB:是一个非常复杂的结构体,里面包含的属性非常多 ^7eb7b0

              1. PID:进程的标识符

                • 同一时刻,一个机器的多个进程之间 PID 是唯一的,不会重复,系统内部的很多操作,都是通过 PID 找到进程的
                  image.png|262
              2. 内存指针(一组):描述进程依赖的指令和数据在内存的哪个区域

                • 操作系统运行 exe,就会读取 exe 中的指令和数据,加载到内存中,所以就会有内存地址
                • 侧面表现出进程的执行需要一定的内存资源
              3. 文件描述符表(顺序表/数组):描述了进程打开了哪些文件

                • 对应到硬盘上的数据
                • 侧面表现出进程的执行需要一定的硬盘资源
                • 进程中,打开了某个文件,就会在顺序表中添加一项
              4. 进程状态

                • 就绪状态:可以随时被调度到 CPU 上执行指令
                • 阻塞状态:此状态下的进程,无法调度到 CPU 上执行
                  之所以阻塞,是因为要做一些其他的工作,比如进行 IO 操作(读写硬盘/读写网卡…)
                  • 典型代码:scanf/Scanner 等待控制台输入的时候会阻塞住,啥时候输入好,啥时候继续执行
                • 还有其他状态,此处不展开
              5. 进程优先级

                • 谁先谁后,谁多谁少
              6. 进程的上下文

                • 分时复用,一个进程执行一会之后,就会从 CPU 上调度走,过一段时间,还会调度回 CPU,此时就要沿着上次执行的结果继续往后执行
                • 把之前执行的中间结果(各种 CPU 寄存器中的值)保存起来,以备下次使用
              7. 进程的记账信息

                • 优先级的加持之下,使不同的进程吃到的资源差异越来越大

                • 操作系统统计每个进程在 CPU 上执行的时间,根据这个来进一步地调整调度地策略

                • 上面四点都是用来支持进程的调度的,和日常开发息息相关。
                  计算机里的进程很多,且都需要执行,CPU 负责执行,每个核心可以执行一个进程,但其他的怎么办呢? ^87b85a

                  • 关键点就是四个字“分时复用
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值