CPU相关的科普知识

本文

主要对涉及CPU的一些基本知识和概念进行简单描述,作为科普知识。

版本 说明
0.1 初版发布

参考

各种网络资源。

CPU和SOC的区别

SoC = System on Chip。芯片的发展方向:从CPU到SoC,现在已经没有纯粹的CPU了,都是SoC,ARM出卖的内核其实就是CPU(当然还需要总线),各种外设是半导体厂商自己添加的。

外设就是外部设备。SoC中外设大部分都跑进去了,芯片设计的趋势是更大集成度,在SoC内做成单芯片解决方案。

RISC和CISC

  • complex instruction set computer复杂指令集CPU。CISC体系的设计理念是用最少的指令来完成任务(譬如计算乘法只需要一条MUL指令即可),因此CISC的CPU本身设计复杂、工艺复杂,但好处是编译器好设计。CISC出现较早,至今Intel还一直采用CISC设计。
  • Reduced Instruction-Set Computer精简指令集CPU。RISC的设计理念是让软件来完成具体的任务,CPU本身仅提供基本功能指令集。因此RISC CPU的指令集中只有很少的指令,这种设计相对于CISC,CPU的设计和工艺简单了,但是编译器的设计变难了。
  • 发展趋势:没有纯粹的RISC或CISC,发展方向是RISC与CISC结合,形成一种介于2者之间的CPU类型。

统一编址和独立编址?

内存通过CPU的地址总线来寻址定位,然后通过CPU数据总线来读写。CPU的地址总线的位数是CPU设计时确定的,因此一款CPU所能寻址的范围是一定的,而内存是需要占用CPU的寻址空间的。内存与CPU的这种总线式连接方式是一种直接连接,优点是效率高访问快,缺点是资源有限,扩展性差。

IO指的是与CPU连接的各种外设。CPU访问各种外设有2种方式:一种是类似于访问内存的方式,即把外设的寄存器当作一个内存地址来读写,从而以访问内存相同的方式来操作外设,叫IO与内存统一编址方式;另一种是使用专用的CPU指令来访问某种特定外设,叫IO与内存独立编址。

IO与内存统一编址方式,优势是IO当作内存来访问,编程简单;缺点是IO也需要占用一定的CPU地址空间,而CPU的地址空间是有限资源。IO与内存独立编织方式,优势是 不占用CPU地址空间,缺点是CPU设计变复杂了。

冯诺依曼结构和哈佛结构

  • 程序与数据:
    • 程序是我们写好的源代码经过编译、汇编之后得到的机器码,这些机器码可以拿给CPU去解码执行,CPU不会也不应该去修改程序,所以程序是只读的。
    • 数据是程序运行过程中定义和产生的变量的值,是可以读写的,程序运行实际就是为了改变数据的值。
  • 冯诺依曼结构和哈佛结构:
    • 程序和数据都放在内存中,且不彼此分离的结构称为冯诺依曼结构。冯诺依曼结构中程序和数据不区分的放在一起,因此安全和稳定性是个问题,好处是处理起来简单。
    • 程序和数据分开独立放在不同的内存块中,彼此完全分离的结构称为哈佛结构。哈佛结构中程序(一般放在ROM、flash中)和数据(一般放在RAM中)独立分开存放,因此好处是安全和稳定性高,缺点是软件处理复杂一些(需要统一规划链接地址等)

外部存储和内部存储器

从冯诺依曼的存储程序工作原理以来,计算机就分为了运算器、控制器、存储器和输入输出设备,这里的存储器就是指内部存储器,简称内存。而外部存储器是作为辅助存储的,比如硬盘、U盘、光盘等,准确来说它们属于外设/输入输出设备。内存与地址空间直接映射,这里也就是物理地址,可以通过地址&数据总线与CPU直接相连,而外部存储器和CPU连接不是通过地址&数据总线直接相连,因为地址空间不够用,一般都是通过专门的接口来连接的。在CPU运行时,需要先将外存的程序和数据搬移到内存,才能正常执行。直观来说就是外存只能保证你能存更多东西,要想运行速度块,需要增加内存。

外存和内存根据各自需要,使用不同的存储介质,内存一般使用DDR(Double Data Rate双倍速率同步动态随机存储器),容量小,断电后数据会丢失,单位容量价格较高,访问速度较快(为什么是较高较快,下文解释);外存使用的种类就比较多了,动态硬盘、机械硬盘、光盘、U盘等等,容量大,单位容量价格低,访问速度慢,断电后数据不会丢失。

之所以说内存的单位容量价格较高和访问速度较快,是因为还有缓存(cache),缓存一般使用SRAM(Static Random-Access Memory)静态随机存储器,之所以说静态与动态相比只要保持供电不需要刷电就能一直保存数据(与具体晶体管实现方式不同),SRAM访问速度最快,可以接近CPU的运行速度(内存和CPU运行速度相差近三个量级),但是单位容量价格最贵,单位容量占用芯片面积最多。

虚拟地址和物理地址

地址空间

地址空间其实是一个比较抽象的概念,我们可以把它想象成一个长的数组,每个数组元素占一个字节。那么这个数组的长度就由地址空间长度来决定。例如:我们32位的系统的地址空间就是我们的2^32字节(4GB),而64位的地址空间大小就是2^64个字节。这也就解释了在我们32位的操作系统,为什么最大只能支持4GB的有效内存。

物理地址

物理地址:物理地址空间是实在的存在于计算机中的一个实体,在每一台计算机中保持唯一独立性。我们可以称它为物理内存;如在32位的机器上,物理空间的大小理论上可以达到2^32字节(4GB),但如果实际装了512的内存,那么其物理地址真正的有效部分只有512MB = 512 * 1024 KB = 512 * 1024 * 1024 B(0x00000000~0x1fffffff)。其他部分是无效的。

虚拟地址

虚拟地址:虚拟地址并不真实存在于计算机中。每个进程都分配有自己的虚拟空间,而且只能访问自己被分配使用的空间。理论上,虚拟空间受物理内存大小的限制,如给有4GB内存,那么虚拟地址空间的地址范围就应该是0x00000000~0xFFFFFFFF。每个进程都有自己独立的虚拟地址空间。这样每个进程都能访问自己的地址空间,这样做到了有效的隔离。

为什么要设置虚拟地址

在早期的计算机中,程序是直接运行到物理内存(可以理解为内存条上的内存)上的。也就是说,程序运行的时候直接访问的就是物理地址。如果,我们的一个计算机只运行一个程序,那么只有这个程序所需要的内存空间不超过物理内存空间的大小,就不会有问题。但是,我们正在希望的是在某个时候同时运行多个程序。那么这个时候,就会有个一个问题,计算机如何把有限的物理内存分配给多个程序使用呢?

某台计算机总的内存大小是128M,现在同时运行两个程序A和B,A需占用内存10M,B需占用内存110。计算机在给程序分配内存时会采取这样的方法:先将内存中的前10M分配给程序A,接着再从内存中剩余的118M中划分出110M分配给程序B。这种分配方法可以保证程序A和程序B都能运行,但是这种简单的内存分配策略问题很多。

问题1:进程地址空间不隔离。由于程序都是直接访问物理内存,所以恶意程序可以随意修改别的进程的内存数据,以达到破坏的目的。有些非恶意的,但是有bug的程序也可能不小心修改了其它程序的内存数据,就会导致其它程序的运行出现异常。这种情况对用户来说是无法容忍的,因为用户希望使用计算机的时候,其中一个任务失败了,至少不能影响其它的任务。

问题2:内存使用效率低。在A和B都运行的情况下,如果用户又运行了程序C,而程序C需要20M大小的内存才能运行,而此时系统只剩下8M的空间可供使用,所以此时系统必须在已运行的程序中选择一个将该程序的数据暂时拷贝到硬盘上,释放出部分空间来供程序C使用,然后再将程序C的数据全部装入内存中运行。可以想象得到,在这个过程中,有大量的数据在装入装出,导致效率十分低下。

问题3:程序运行的地址不确定。当内存中的剩余空间可以满足程序C的要求后,操作系统会在剩余空间中随机分配一段连续的20M大小的空间给程序C使用,因为是随机分配的,所以程序运行的地址是不确定的。但是我们的某些硬件是需要在固定的地址上去开始运行的,但是如果这个地址后边被我们的程序占有,那么我们对这块内存的修改,就可能导致某些硬件不可用了。

为了解决上述问题,人们想到了一种变通的方法,就是增加一个中间层,利用一种间接的地址访问方法访问物理内存。按照这种方法,程序中访问的内存地址不再是实际的物理内存地址,而是一个虚拟地址,然后由操作系统将这个虚拟地址映射到适当的物理内存地址上。这样,只要操作系统处理好虚拟地址到物理内存地址的映射,就可以保证不同的程序最终访问的内存地址位于不同的区域,彼此没有重叠,就可以达到内存地址空间隔离的效果。

虚拟地址和物理地址的映射

虚拟地址和物理地址之间的映射是通过MMU(内存管理单元)来完成的。具体映射机制,这里不进行描述了,本文作为科普,更深入的分析留在其他章节。

cpu与核心

  • 物理CPU:物理CPU是相对于虚拟CPU而言的概念,指实际存在的CPU处理器,安装在PC主板或服务器上。需要注意的是这个CPU可能有多个核心。
  • 物理核:CPU中包含的物理内核(核心)个数,比如多核CPU,单核CPU(古老的CPU)。这个多核或者单核已经集成在CPU内部了。
  • 逻辑核和虚拟核:所谓的4核8线程,4核指的是物理核心。用Intel的超线程技术(HT)将物理核虚拟而成的逻辑处理单元,现在大部分的主机的CPU都在使用HT技术,用一个物理核模拟两个虚拟核,即每个核两个线程,总数为8线程。这样在操作系统看来是8个核,但是实际上是1个物理CPU中的4个物理内核。通过超线程技术可以实现单个物理核实现线程级别的并行计算,但是性能比不上两个物理核,因为两个线程共享一套运算资源。

进程和线程

概念

进程是操作系统进行资源(包括cpu、内存、磁盘IO等)分配的最小单位。线程是cpu调度和分配的基本单位。

举例说明: 我们打开的聊天工具,浏览器都是一个进程。进程可能有多个子任务,比如聊天工具要接受消息,发送消息,这些子任务就是线程。资源分配给进程,线程共享进程资源。

对比

对比 进程 线程
定义 序运行的一个实体的运行过程,是系统进行资源分配和调配的一个独立单位 线程是进程运行和执行的最小调度单位
系统开销 创建撤销切换开销大,资源要重新分配和收回 仅保存少量寄存器的内容,开销小,在进程的地址空间执行代码
拥有资产 资源拥有的基本单位 基本上不占资源,仅有不可少的资源(程序计数器,一组寄存器和栈)
调度 的基本单位 独立调度分配的单位
安全性 互独立,互不影响 线程共享一个进程下面的资源,可以互相通信和影响
地址空间 系统赋予的独立的内存地址空间 由相关堆栈寄存器和和线程控制表TCB组成,寄存器可被用来存储线程内的局部变量

线程的切换

cpu给线程分配时间片(也就是分配给线程的时间),执行完时间片后会切换都另一个线程。切换之前会保存线程的状态,下次时间片再给这个线程时才能知道当前状态。从保存线程A的状态再到切换到线程B时,重新加载线程B的状态的这个过程就叫上下文切换。而上下切换时会消耗大量的cpu时间。

串行,并发与并行

  • 串行:多个任务,执行时一个执行完再执行另一个。比如一边吃饭一边看视频。
  • 并发:多个线程在单个核心运行,同一时间一个线程运行,系统不停切换线程,看起来像同时运行,实际上是线程不停切换。比如一会跑去厨房吃饭,一会跑去客厅看视频。
  • 并行:每个线程分配给独立的核心,线程同时运行。比如一边吃饭一边看视频。

文章原创,可能存在部分错误,欢迎指正,联系邮箱 cao_arvin@163.com。