跳转至

CPU

1 cpu组成

随着芯片集成度的不断提高,现代CPU除了含有运算器和控制器外,常常还集成了其它部件,比如高速缓存(Cache)部件、内存控制器等
  • CPU基础知识-CPU的组成 运算器、控制器、寄存器
  • CPU内部主要由运算器、控制器、寄存器三大部分组成。
    • 运算器:负责算术运算(+ - * / 基本运算和附加运算)和逻辑运算(包括 移位、逻辑测试或比较两个值等)。
    • 控制器:负责应对所有的信息情况,调度运算器把计算做好。
    • 寄存器:它们可用来暂存指令、数据和地址。既要对接控制器的命令,传达命令给运算器;还要帮运算器记录处理完或者将要处理的数据。

1.1 控制器

控制器由程序计数器(PC,Program Counter)、指令寄存器(IR,Instruction Register)、指令译码器(ID,Instruction Decoder)、时序产生器(Timing Generator)、操作控制器(Control Unit)组成。
指令寄存器IR,是用来存放当前正在执行的的一条指令,存放的内容来自于数据寄存器(DR,Data Register)。当一条指令需要被执行时,先要把它从内存取到数据寄存器,然后再送到指令寄存器IR中。
指令译码器ID,在计算机执行一条指定的指令时,必须首先分析这条指令的操作码是什么,以决定操作的性质和方法,然后控制计算机的其他各部件协同完成指令表达的功能,这中间的分析工作就是指令译码器ID完成的。
程序计数器PC,用来存放下一条要执行指令的地址,它与存储器(内存)之间有一条直接通路。执行指令时,首先需要根据程序计数器PC中存放的指令地址,将指令由内存取到指令寄存器IR,完成“取指令”的操作。程序计数器PC本身具有自动加1的功能,可以自动给出下一条指令的地址,如此循环,执行每一条指令。
时序产生器,类似于“时间作息表”,给计算机各部分提供工作所需的时间标志,一般是利用定时脉冲的顺序和不同的脉冲间隔来实现。
操作控制器,根据指令所需完成的操作和信号,发出各种微操作命令序列,用以控制所有被控对象,完成指令的执行。
整个控制器的运行逻辑是先按照程序计数器所指出的指令地址,从内存中取出一条指令到指令寄存器IR,然后指令译码器ID对指令进行分析,之后操作控制器根据指令的功能向有关部件发出控制命令,执行控制指令的操作。完成操作之后,程序计数器加1,再重复执行上述操作。

1.2 运算器

运算器,一般最少包括3个寄存器和1个算术逻辑单元(ALU),现代计算机内部往往设有通用寄存器组。

寄存器,一种有限存储容量的高速存储部件,可用来暂存指令、数据和位址。寄存器有很多种类,一般涉及到四则运算的有3类,ACC(Accumulator)为累加器,MQ(Multiplier-Quotient Register)为乘商寄存器,X为操作数寄存器,3类寄存器在完成不同运算时,所存放的操作数类别也各不相同。

运算器

关于乘积高位和乘积低位的概念,以十进制为例,百位就是十位的高位,十位是百位的低位。两个16位数相乘,结果可能会有32位,那左半部分的16位就是乘积高位,存储到ACC中,右半部分的16位就是乘积低位,存储到MQ中。
算术逻辑单元(ALU,Arithmetic and Logic Unit),是算术运算和逻辑运算的部件。算术运算包括加、减、乘的整数运算,逻辑运算是与、或、非和异或等逻辑操作,还有移位、比较和传送等操作。
移位运算,将一个字符向左或向右移动位,或是浮动特定位,包含带符号延伸和无符号延伸,在程序中应用很广泛。

1.3 寄存器

在CPU中至少要有六类寄存器:指令寄存器(IR)、程序计数器(PC)、地址寄存器(AR)、数据寄存器(DR)、累加寄存器(AC)、程序状态字寄存器(PSW)。这些寄存器用来暂存一个计算机字,其数目可以根据需要进行扩充。 1. 数据寄存器
1. 数据寄存器(Data Register,DR)又称数据缓冲寄存器,其主要功能是作为CPU和主存、外设之间信息传输的中转站,用以弥补CPU和主存、外设之间操作速度上的差异。
2. 数据寄存器用来暂时存放由主存储器读出的一条指令或一个数据字;反之,当向主存存入一条指令或一个数据字时,也将它们暂时存放在数据寄存器中。
3. 数据寄存器的作用是 :
1. 作为CPU和主存、外围设备之间信息传送的中转站;
2. 弥补CPU和主存、外围设备之间在操作速度上的差异;
3. 在单累加器结构的运算器中,数据寄存器还可兼作操作数寄存器。 2. 指令寄存器
1. 指令寄存器(Instruction Register,IR)用来保存当前正在执行的一条指令。
2. 当执行一条指令时,首先把该指令从主存读取到数据寄存器中,然后再传送至指令寄存器。
3. 指令包括操作码和地址码两个字段,为了执行指令,必须对操作码进行测试,识别出所要求的操作,指令译码器(Instruction Decoder,ID)就是完成这项工作的。指令译码器对指令寄存器的操作码部分进行译码,以产生指令所要求操作的控制电位,并将其送到微操作控制线路上,在时序部件定时信号的作用下,产生具体的操作控制信号。
4. 指令寄存器中操作码字段的输出就是指令译码器的输入。操作码一经译码,即可向操作控制器发出具体操作的特定信号。 3. 程序计数器
1. 程序计数器(Program Counter,PC)用来指出下一条指令在主存储器中的地址。
2. 在程序执行之前,首先必须将程序的首地址,即程序第一条指令所在主存单元的地址送入PC,因此PC的内容即是从主存提取的第一条指令的地址。
3. 当执行指令时,CPU能自动递增PC的内容,使其始终保存将要执行的下一条指令的主存地址,为取下一条指令做好准备。若为单字长指令,则(PC)+1àPC,若为双字长指令,则(PC)+2àPC,以此类推。
4. 但是,当遇到转移指令时,下一条指令的地址将由转移指令的地址码字段来指定,而不是像通常的那样通过顺序递增PC的内容来取得。 5. 因此,程序计数器的结构应当是具有寄存信息和计数两种功能的结构。 4. 地址寄存器
1. 地址寄存器(Address Register,AR)用来保存CPU当前所访问的主存单元的地址。
2. 由于在主存和CPU之间存在操作速度上的差异,所以必须使用地址寄存器来暂时保存主存的地址信息,直到主存的存取操作完成为止。
3. 当CPU和主存进行信息交换,即CPU向主存存入数据/指令或者从主存读出数据/指令时,都要使用地址寄存器和数据寄存器。
4. 如果我们把外围设备与主存单元进行统一编址,那么,当CPU和外围设备交换信息时,我们同样要使用地址寄存器和数据寄存器。

  1. 累加寄存器

    1. 累加寄存器通常简称累加器(Accumulator,AC),是一个通用寄存器。
    2. 累加器的功能是:当运算器的算术逻辑单元ALU执行算术或逻辑运算时,为ALU提供一个工作区,可以为ALU暂时保存一个操作数或运算结果。
    3. 显然,运算器中至少要有一个累加寄存器。
  2. 程序状态字寄存器

    1. 程序状态字(Program Status Word,PSW)用来表征当前运算的状态及程序的工作方式。
    2. 程序状态字寄存器用来保存由算术/逻辑指令运行或测试的结果所建立起来的各种条件码内容,如运算结果进/借位标志(C)、运算结果溢出标志(O)、运算结果为零标志(Z)、运算结果为负标志(N)、运算结果符号标志(S)等,这些标志位通常用1位触发器来保存。
    3. 除此之外,程序状态字寄存器还用来保存中断和系统工作状态等信息,以便CPU和系统及时了解机器运行状态和程序运行状态。
    4. 因此,程序状态字寄存器是一个保存各种状态条件标志的寄存器。

2 时钟频率、CPU 周期、时钟周期、指令周期

通常对于大多数处理器来说,一个机器周期需要十二个时钟周期才能完成。一个指令周期可能需要一个或最多四个机器周期来执行一条指令。

2.1 时钟频率

  • 时钟频率:又称时钟速度,是 cpu 每秒执行时钟周期的数量。比如 1GHz CPU 为 1000,000,000 次每秒。10 亿次/秒

2.2 时钟周期

2.3 CPU 周期

  • CPU 周期:又称机器周期,在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶段,每一阶段完成一项工作。
  • 例如,取指令、存储器读、存储器写等,这每一项工作称为一个基本操作注意:每一个基本操作都是由若干 CPU 最基本的动作组成)。完成一个基本操作所需要的时间称为机器周期。通常用内存中读取一个指令字的最短时间来规定 CPU 周期。

2.4 指令周期

  • 指令周期:是指计算机从取指到指令执行完毕的时间
  • 计算机执行指令的过程可以分为以下三个步骤:
  • Fetch(取指),也就是从 PC 寄存器里找到对应的指令地址,根据指令地址从内存里把具体的指令,加载到指令寄存器中,然后把 PC 寄存器自增,好在未来执行下一条指令。
  • Decode(译码),也就是根据指令寄存器里面的指令,解析成要进行什么样的操作,是 R、I、J 中的哪一种指令,具体要操作哪些寄存器、数据或者内存地址。
  • Execute(执行指令),也就是实际运行对应的 R、I、J 这些特定的指令,进行算术逻辑操作、数据传输或者直接的地址跳转。
  • 在取指令的阶段,我们的指令是放在存储器(也就是内存)里的,实际上,通过 PC 寄存器指令寄存器取出指令的过程,是由控制器(Control Unit)操作的。指令的解码过程,也是由控制器进行的。一旦到了执行指令阶段,无论是进行算术操作、逻辑操作的 R 型指令,还是进行数据传输、条件分支的 I 型指令,都是由算术逻辑单元(ALU)操作的,也就是由运算器处理的。不过,如果是一个简单的无条件地址跳转,那么我们可以直接在控制器里面完成,不需要用到运算器。

2.5 周期之间的关系

  • 指令周期(Instruction Cycle):取出并执行一条指令的时间。
  • CPU 周期:一条指令执行过程被划分为若干阶段,每一阶段完成所需时间。
  • 时钟周期(Clock Cycle):又称震荡周期,是处理操作的最基本单位。

3 CPU上下文

title: 什么时cpu上下文?
CPU 上下文是**CPU 寄存器和程序计数器**
  • CPU 上下文切换指的是:把前一个任务的 CPU 上下文保存起来,然后加载新任务的上下文到这些寄存器和程序计数器上,最后再跳转到程序计数器所指的新位置,运行新的任务。被保存下来的上下文会存储在系统内存中,等任务重新调度执行时再次加载进来。

3.1 六种常见的上下文切换场景

  1. 函数调用
  2. 中断与异常
  3. 系统调用
  4. 进程
  5. 线程
  6. 虚拟机

3.2 六种上下文切换场景的对比

函数调用和系统调用是用户主动发起的,因此可以通过ABI约定来避免不必要的保存恢复。其他几种场景通常都要达到对应用程序透明的效果,因此切换后可能被修改的状态都应该被保存和恢复。

场景 上下文切换时保存和恢复的内容
函数调用 部分寄存器(包括栈帧相关的$sp,$fp)、返回地址
中断和异常 (通常情况)全部定点寄存器、异常现场信息、异常相关信息
系统调用 部分定点寄存器(包括栈帧相关寄存器)、异常现场信息
线程 全部用户态寄存器、TLS、当前PC等相关信息
进程 全部用户态寄存器、页表基址等控制寄存器、当前PC等相关信息
虚拟机 虚拟CPU状态(寄存器、必要的特权资源等)

4 CPU时间片

title: cpu时间片的作用?
由于有时间片的存在,可以让我们同时打开多个程序。每个程序获取cpu资源超过一个时间片后,会被系统剥夺,等待下一次时间片机会。

时间片:(timeslice)又称为“量子(quantum)”或“处理器片(processor slice)”是分时操作系统分配给每个正在运行的进程微观上的一段CPU时间(在抢占内核中是:从进程开始运行直到被抢占的时间)。时间片通常很短(在Linux上为5ms-800ms

4.1 cpu 时间消耗表

  • cpu 时间片消耗表|cpu消耗表
  • cpu时间片大小通常为10~100ms,在 Windows 操作系统上,一个时间片通常在十几毫秒(译者注:默认 15.625ms)
  • 进程时间片:20ms
  • 进程上下文切换:10ms
  • 线程上下文切换 :3.8μs,这个分为同进程线程和非同进程线程他们时间不一样
  • 中断上下文切换:很短
  • 存储耗费时间
  • L1的存取速度:4个CPU时钟周期大概2ns
  • L2的存取速度:11个CPU时钟周期大概5ns
  • L3的存取速度:39个CPU时钟周期大概20ns
  • RAM内存的存取速度:107个CPU时钟周期大概53ns
  • 固态硬盘访问10-100us
  • 机械硬盘访问1-10ms

4.2 时间片轮转(RR)调度算法

  • 时间片轮转(RR)调度算法 该算法中,将一个较小时间单元定义为时间量或时间片。时间片的大小通常为 10~100ms。就绪队列作为循环队列。CPU 调度程序循环整个就绪队列,为每个进程分配不超过一个时间片的 CPU。 RR调度算法是抢占的。

为了实现 RR 调度,我们再次将就绪队列视为进程的 FIFO 队列。新进程添加到就绪队列的尾部。CPU 调度程序从就绪队列中选择第一个进程,将定时器设置在一个时间片后中断,最后分派这个进程。

接下来,有两种情况可能发生。 1. 进程可能只需少于时间片的 CPU 执行。对于这种情况,进程本身会自动释放 CPU。调度程序接着处理就绪队列的下一个进程。 2. 否则,如果当前运行进程的 CPU 执行大于一个时间片,那么定时器会中断,进而中断操作系统。然后,进行上下文切换,再将进程加到就绪队列的尾部,接着 CPU 调度程序会选择就绪队列内的下一个进程。

5 中断

CPU收到中断信号后,会暂停当前CPU的执行进程,转去执行某个特定的程序。 - 中断源即中断的源头,比如用户敲击一下键盘,单击一下鼠标,或者DMA的一次传输完成了,对应的控制器会产生一个中断信号。 - 中断信号可以是一根信号线,也可以是一个消息包。这个中断信息会传送到中断控制器中。 - 中断控制器是负责中断汇集、记录和转发的硬件逻辑。中断控制器一般都具有可编程功能,因此被称为可编程中断控制器(Programmable Interrupt Controller,简称PIC)。

5.1 中断的过程

  1. 中断源发出中断信号到中断控制器;
  2. 中断控制器产生中断请求给CPU;
  3. CPU发出中断响应,并读取中断类型码;
  4. CPU根据中断类型码执行对应的中断服务程序;
  5. CPU从中断服务程序返回,中断结束。

6 同步机制

多任务是操作系统最为关键的特性之一,现代操作系统中可能同时存在多个进程,每个进程又可能包含多个同时执行的线程。在Linux操作系统中,某个线程正在操作的数据很可能也在被另一个线程访问。 - 并发访问的线程可能有以下来源: 1. 另一个CPU核上的线程。这是真正的多处理器系统。 2. 处于中断上下文的线程。中断处理程序打断当前线程的执行。 3. 因调度而抢占的另一线程。中断处理后调度而来的其他内核线程。 - 同步机制通常包括基于互斥(Mutual Exclusive)和非阻塞(Non-Blocking)两类。

title: 基于锁的资源保护和线程同步有以下缺点
1. 若持有锁的线程死亡、阻塞或死循环,则其他等待锁的线程可能永远等待下去。
2. 即使冲突的情况非常少,锁机制也有获取锁和释放锁的代价。
3. 锁导致的错误与时机有关,难以重现。
4. 持有锁的线程因时间片中断或页错误而被取消调度时,其他线程需要等待。

6.1 原子操作

title: 什么是原子操作?
原子(atom) 本意是“不能被进一步分割的最小粒子”, 而原子操作(atomic operation)意为“不可被中断的一个或一系列操作”。 对原子操作的简单描述就是: 多个线程执行一个操作时, 其中任何一个线程要么完全执行完此操作, 要么没有执行此操作的任何步骤, 那么这个操作就是原子的。 原子操作是其他内核同步方法的基石
  • 在单处理器系统(UniProcessor) 中, 能够在单条指令中完成的操作都可以认为是“原子操作”, 因为中断只能发生于指令之间。
  • 在多核CPU的时代, 体系中运行着多个独立的CPU, 即使是可以在单个指令中完成的操作也可能会被干扰。 典型的例子就是decl指令(递减指令) , 它细分为三个过程: “读->改->写”, 涉及两次内存操作。 CPU 提供三种独立的原子锁机制: 原子保证操作加 LOCK 指令前缀缓存一致性协议

6.2 内存屏障

6.2.1 什么是内存屏障?,为什么需要内存屏障?

首先,为了性能编译器和处理器都会对指令进行重排序。 - 什么是内存屏障:一条指令,该指令可以对编译器(软件)和处理器(硬件)的指令重排做出一定的限制,比如,一条内存屏障指令可以禁止编译器和处理器将其后面的指令移到内存屏障指令之前。 - 为什么需要内存屏障:编译器和处理器指令重排只能保证在单线程执行下逻辑正确,在多个线程同时读写多个变量的情况下,如果不对指令重排作出一定限制,代码的执行结果会根据指令重排后的顺序产生不同的结果