计算机操作系统(1)

可不可以计算一个人程序写得好不好?

  1. 芯片:计算能源:电能供给给芯片,芯片中的一种电子元件晶振(也就是石英晶体)通电后产生震荡,震荡会产生频率稳定的脉冲信号。通常这是一种高频的脉冲信号,每秒可达百万次。然后,我们通过谐振效应发放这个信号,形成方波。再通过电子元件调整这种脉冲的频率,把脉冲信号转换为我们需要的频率,这就形成了驱动芯片工作的时钟信号。这种信号的频率,我们也称作芯片的时钟频率。最后,时钟信号驱动着芯片工作,就像人体的脉搏一样,每一次脉冲到来,都让芯片的状态发生一次变化,用这种方法,最终存储器中的指令被一行行执行。指令被执行,其实就是数据被计算,这就是我说的计算能量。

  2. 摩尔定律:计算能力的发展:当价格不变时,集成电路中可容纳的晶体管数目约每隔 18~24 个月就会增加一倍,性能也将提升一倍。这一定律揭示了信息技术发展的速度,但到今天,摩尔定律失效了。因为随着芯片越来越小,在尺寸和散热等方面已经挑战了人类的极限,芯片中无法再放入更多的电子元件了。

  3. 公理化体系和不完备性定理:最早在 19 世纪初,德国著名数学家希尔伯特提出:这个世界可以建立一套完善的公理体系,由少数几个公理出发,推导出所有的定理和推论。这样就可以逐渐通过这种方法将世界上的万事万物都统一到一个体系中。美籍数学家哥德尔就提出了哥德尔不完备性定理,内容是:即便在完善的公理体系中仍然可以找到不能被证明也不能被证伪的命题。

  4. 图灵机和可计算理论:1936 年,被誉为人工智能之父的阿兰·图灵提出了图灵机,它是一种不断执行指令的抽象计算机。之所以说抽象,是因为图灵并没有真的造出这台机器,而是把它当成理论去和大家探讨可计算问题。图灵发现如果一个问题是可计算的,那么它的解决方案就必须可以被具化成一条条的指令,也就是可以使用图灵机处理。因此,不能使用图灵机处理的问题,都是不可计算的问题。

  5. 停机问题:我们也无法实现用一个通用程序去判断另一个程序是否会停止。不能因为这个程序执行了 1 天,就判定它不会停止,也不能因为这个程序执行了 10 年,从而得出它不会停止的结论。这个问题放到图灵机领域,叫作停机问题,我们无法给出一个判断图灵机是否会停机的通用方法,因此停机问题是一个经典的不可计算问题。

  6. 计算能力的边界在哪里?我们可以把世界上想解决的事情都称作问题,解决问题往往需要消耗芯片的计算能力,这通常称作时间开销,另外解决问题还需要消耗内存,称作空间开销。

  7. 问题的分类:世界上有一类问题,无论我们消耗多少时间和空间也无法解决,这类问题就包括“停机问题”,称作不可计算问题,我们无法用计算机精确地解决这类问题。另外在可计算的问题中,有困难问题,也有简单问题,我们通常用复杂度来衡量,比如:

    • “求数组第 10 个元素”,计算这种问题,时间开销、空间开销都不会随着问题规模增长,我们记为 O(1);

    • “求数组中的最大值”,计算这种问题,时间开销会随着数组规模线性增大,记作 O(N),N 是问题的规模;

    • 当然也有更加复杂的数学模型,比如说O(N3)、O(N4)、O(N100)等。

    按照摩尔定律所说,人类的计算能力每 18~24 个月翻一倍,我们的计算能力在呈指数形式上升。因此,在所有可以计算的问题中,像 O(N1000)的问题,虽然现在的计算能力不够,但是相信在遥远的未来,我们会拥有能力解决。这种我们有能力解决的问题,统称为多项式时间( Polynomial time)问题。另外,还有一类问题复杂度本身也是指数形式的问题,比如 O(2N)的问题。这类型的问题随着规模 N 上升,时间开销的增长速度和人类计算能力增长速度持平甚至更快。因此虽然这类问题可以计算,但是当 N 较大时,因为计算能力不足,最终结果依然无法被解决。

  8. 人工智能:虽然很多问题不能解决,但可以努力让计算机的解决方案超过人类的水平,这就是人工智能。

64 位和 32 位比较有哪些优势?

如果是软件,那么我们的数据库有 32 位和 64 位版本;

如果是操作系统,那么在阿里云上选择 Centos 和 Debian 版本的时候,也会有 32/64 版本;

如果是 CPU,那么有 32 位 CPU,也有 64 位 CPU。

  1. 图灵机的构造:想要学懂程序执行的原理,就要从图灵机说起了。它在计算机科学方面有两个巨大的贡献:

    • 第一,它清楚地定义了计算机能力的边界,也就是可计算理论;

    • 第二,它定义了计算机由哪些部分组成,程序又是如何执行的。

  2. 计算机的组成部分:计算机结构分成以下 5 个部分:

    • 输入设备和输出设备:输入设备向计算机输入数据,计算机经过计算,将结果通过输出设备向外界传达。如果输入设备、输出设备想要和 CPU 进行交互,比如说用户按键需要 CPU 响应,这时候就需要用到控制总线。

    • 内存:在冯诺依曼模型中,程序和数据被存储在一个被称作内存的线性排列存储区域。存储的数据单位是一个二进制位,英文是 bit。最小的存储单位叫作字节,也就是 8 位,英文是 byte,每一个字节都对应一个内存地址。内存地址由 0 开始编号,比如第 1 个地址是 0,第 2 个地址是 1, 然后自增排列,最后一个地址是内存中的字节数减 1。我们通常说的内存都是随机存取器,也就是读取任何一个地址数据的速度是一样的,写入任何一个地址数据的速度也是一样的。

    • 中央处理器:冯诺依曼模型中 CPU 负责控制和计算。为了方便计算较大的数值,CPU 每次可以计算多个字节的数据。

      • 如果 CPU 每次可以计算 4 个 byte,那么我们称作 32 位 CPU;

      • 如果 CPU 每次可以计算 8 个 byte,那么我们称作 64 位 CPU。

      CPU 位数越大,可以计算的数值就越大。但是在现实生活中不一定需要计算这么大的数值。CPU 要进行计算,比如最简单的加和两个数字时,因为 CPU 离内存太远,所以需要一种离自己近的存储来存储将要被计算的数字。这种存储就是寄存器。寄存器就在 CPU 里,控制单元和逻辑运算单元非常近,因此速度很快。

      • 寄存器中有一部分是可供用户编程用的,比如用来存加和指令的两个参数,是通用寄存器。

      • 还有一部分寄存器有特殊的用途,叫作特殊寄存器。比如程序指针,就是一个特殊寄存器。它存储了 CPU 要执行的下一条指令所在的内存地址。注意,程序指针不是存储了下一条要执行的指令,此时指令还在内存中,程序指针只是存储了下一条指令的地址。

      • 下一条要执行的指令,会从内存读入到另一个特殊的寄存器中,这个寄存器叫作指令寄存器。指令被执行完成之前,指令都存储在这里。

    • 总线:CPU 和内存以及其他设备之间,也需要通信,因此我们用一种特殊的设备进行控制,就是总线。总线分成 3 种:

      • 一种是地址总线,专门用来指定 CPU 将要操作的内存地址。

      • 还有一种是数据总线,用来读写内存中的数据。

      当 CPU 需要读写内存的时候,先要通过地址总线来指定内存地址,再通过数据总线来传输数据。

      • 最后一种总线叫作控制总线,用来发送和接收关键信号,中断信号,还有设备复位、就绪等信号,都是通过控制总线传输。同样的,CPU 需要对这些信号进行响应,这也需要控制总线。

    这个模型也被称为冯诺依曼模型

线路位宽:数据通过线路传递,通过操作电压,低电压是 0,高电压是 1。这种一个 bit 一个 bit 发送的方式,我们叫作串行。如果希望每次多传一些数据,就需要增加线路,也就是需要并行

 

  1. 程序的执行过程:

    1. 1.首先,CPU 读取 PC 指针指向的指令,将它导入指令寄存器。具体来说,完成读取指令这件事情有 3 个步骤:

    • CPU 的控制单元操作地址总线指定需要访问的内存地址(简单理解,就是把 PC 指针中的值拷贝到地址总线中)。

    • CPU 通知内存设备准备数据(内存设备准备好了,就通过数据总线将数据传送给 CPU)。

    • CPU 收到内存传来的数据后,将这个数据存入指令寄存器。

    1. 2.然后,CPU 分析指令寄存器中的指令,确定指令的类型和参数。

    1. 3.如果是计算类型的指令,那么就交给逻辑运算单元计算;如果是存储类型的指令,那么由控制单元执行。

    1. 4.PC 指针自增,并准备获取下一条指令。

  2. 指令:构造指令的过程,叫作指令的编码,通常由编译器完成;解析指令的过程,叫作指令的解码,由 CPU 完成。由此可见 CPU 内部有一个循环:

    • 首先 CPU 通过 PC 指针读取对应内存地址的指令,我们将这个步骤叫作 Fetch,就是获取的意思。

    • CPU 对指令进行解码,我们将这个部分叫作 Decode。

    • CPU 执行指令,我们将这个部分叫作 Execution。

    • CPU 将结果存回寄存器或者将寄存器存入内存,我们将这个步骤叫作 Store。

    计算机操作系统-学习笔记(1)_寻址

    上面 4 个步骤,我们叫作 CPU 的指令周期。CPU 的工作就是一个周期接着一个周期,周而复始。

  3. 指令的类型:指令从功能角度来划分,大概有以下 5 类:

    • I/O 类型的指令,比如处理和内存间数据交换的指令 store/load 等;再比如将一个内存地址的数据转移到另一个内存地址的 mov 指令。

    • 计算类型的指令,最多只能处理两个寄存器,比如加减乘除、位运算、比较大小等。

    • 跳转类型的指令,用处就是修改 PC 指针。比如编程中大家经常会遇到需要条件判断+跳转的逻辑,比如 if-else,swtich-case、函数调用等。

    • 信号类型的指令,比如发送中断的指令 trap。

    • 闲置 CPU 的指令 nop,一般 CPU 都有这样一条指令,执行后 CPU 会空转一个周期。

    指令还有一个分法,就是寻址模式,比如同样是求和指令,可能会有 2 个版本:

    • 将两个寄存器的值相加的 add 指令。

    • 将一个寄存器和一个整数相加的 addi 指令。

    另外,同样是加载内存中的数据到寄存器的 load 指令也有不同的寻址模式:

    • 比如直接加载一个内存地址中的数据到寄存器的指令la,叫作直接寻址。

    • 直接将一个数值导入寄存器的指令li,叫作寄存器寻址。

    • 将一个寄存器中的数值作为地址,然后再去加载这个地址中数据的指令lw,叫作间接寻址。

  4. 指令的执行速度:之前我们提到过 CPU 是用石英晶体产生的脉冲转化为时钟信号驱动的,每一次时钟信号高低电平的转换就是一个周期,我们称为时钟周期。CPU 的主频,说的就是时钟信号的频率。比如一个 1GHz 的 CPU,说的是时钟信号的频率是 1G。

  5. 64 位和 32 位比较有哪些优势?

    • 如果说的是63为宽CPU,两个优势:

      • 64位CPU可以执行更大数字的运算,这个优势在普通应用上不明显,但是对于数值计算比较多的应用就非常明显。

      • 64为CPU可以寻址更大的内存空间。

    • 如果说的是32位或64位说的是程序,那么说的是指令是64位还是32位,32位指令在64位机器上执行,困难不大,可以兼容,如果是64位指令,在32位机器上执行就困难了,因为32位指令在64位机器执行的时候,需要的是一套兼容机制,但是64位指令在32位机器上执行,32位的寄存器都存不下指令的参数、

    • 操作系统也是一种程序,如果是64位操作系统,也就是操作系统中程序的指令都是64位指令,因此不能安装在32位机器上。