当前位置: 首页 > backend >正文

笔记:现代操作系统:原理与实现(1)

第二章 硬件结构

冯诺依曼结构组成部分

  • 中央处理单元(Central Processing Unit, CPU):主要负责运算逻辑控制。按照程序中的指令进行计算,并且根据条件执行程序中的不同部分(顺序或跳转执行)。
  • 存储器(memory unit):负责存储程序指令和数据,以及保存程序执行的中间结果和最终结果。在现代计算机中,存储器通常包括寄存器、CPU 缓存、内存等存储层次。
  • 输入输出(Input and Output, I/O):负责与外界进行交互,从外界获得输入,将结果向外界输出。诸如键盘、鼠标、显示器、打印机以及网卡等外设,都属于此类设备。

在这里插入图片描述

CPU与指令集架构

指令集架构(Instruction Set Architecture, ISA)是 CPU 和软件之间的桥梁。ISA 包含指令集、特权级、寄存器、执行模式、安全扩展、性能加速扩展等诸多方面,本节将对相关内容进行介绍。

指令集

指令集是 ISA 的重要组成部分,通常包含一系列不同功能的指令,用于数据搬移、计算、内存访问、过程调用等。

以Aarch64为例,其指令集属于精简指令集计算机(Reduced Instruction Set Computer, RISC),每条指令的长度固定为 4 字节,指令类型包括:

  • 数据搬移指令(如 mov);
  • 寄存器计算指令(如加法指令 add、减法指令 sub);
  • 内存读写指令(如内存加载指令 ldr、内存写入指令 str);
  • 跳转指令(如无条件跳转指令 b);
  • 过程调用指令(如调用指令 bl、返回指令 ret);
  • 特权指令(如读取系统寄存器指令 mrs、写入系统寄存器指令 msr)等。

ARMv8 支持两种执行模式——AArch32 与 AArch64,前者主要为了向后兼容,本书主要关注后者,即支持 64 位虚拟地址的 AArch64,为了方便表述也称之为 AArch64 体系结构。

x86-64 体系结构的指令集属于复杂指令集计算机(Complex Instruction Set Computer, CISC)。通常来说,相比于 RISC,CISC 具有指令数量更多、指令编码长度可变和指令寻址方式多样等特点。

add:  用于执行加法运算adrp :  Address Page - 计算页面对齐的地址,页面大小通常是 4KB = 0x1000
str : 将寄存器中的数据存储到内存地址str w0, [x1] : 将 w0 存储到 x1 指向的地址
stp : STP 用于将两个寄存器的值存储到内存中,通常是连续的两个内存地址上。			
strb : 将一个源寄存器中的最低一个字节(8 位)的数据,写入到内存中的某个地址			b <label>/<address>: 无条件跳转到指定label或地址
br : 间接跳转:跳转到寄存器中存储的地址
cbnz:  比较寄存器 Xt 的值是否为 非零,非零则跳转
b.eq\b.ne : 与cmp组合使用,相等/不等则跳转
b.gt : 比较是否大于nop : No Operation

gdb命令

p/x *(char **)语法含义:
/x打印16进制,/s打印字符串,/d打印十进制
* :解引用操作符,获取指针指向的值
(char **) : 对于**来说,charint\double没有区别,主要易于理解;**地址中存储的为指针,*的话为存储的是具体的变量值

特权级

AArch64 中的特权级被称为异常级别(Exception Level, EL),共有四种特权级。

在这里插入图片描述

  • EL0:最低的特权级,应用程序通常运行在该特权级,也称为用户态
  • EL1:操作系统通常运行在该特权级,也称为内核态
  • EL2:在虚拟化场景下需要,虚拟机监控器(Virtual Machine Monitor, VMM,也称为 Hypervisor)通常运行在该特权级。
  • EL3:和安全特性 TrustZone 相关,负责普通世界(normal world)和安全世界(secure world)之间的切换。

由于通常应用程序运行在 EL0 而操作系统运行在 EL1,所以主要介绍 EL0 与 EL1 之间的常见切换场景。一般来说,从 EL0(应用程序)切换到 EL1(操作系统)的可能场景有三种:

  1. 应用程序需要调用操作系统提供的系统调用,此时应用程序会通过执行 svc(特权调用,supervisor call)指令将 CPU 特权级从 EL0 切换到 EL1。(同步)
  2. 应用程序执行了一条指令,而该指令触发了异常(exception),该异常导致 CPU 特权级从 EL0 切换到 EL1。例如,应用在执行一条访存指令时,触发了缺页异常(page fault),从而切换到操作系统内核进行处理。(同步)
  3. 应用程序在执行的过程中,CPU 收到一个来自外设的中断(interrupt),该中断也会导致 CPU 特权级从 EL0 切换到 EL1。(异步)

EL0和EL1之间切换的基本流程

在这里插入图片描述

在此过程中CPU保存的内容包括:

  • 触发异常的指令地址,即程序计数器(PC)
  • 异常原因
  • 保存SP_EL0(应用程序使用的栈指针)
  • CPU相关状态

当发生特权级切换时

  • CPU 会读取 VBAR_EL1(向量基地址寄存器,Vector Base Address Register)来获得异常向量表(exception vector table)的基地址
  • 根据异常原因(ESR_EL1 中保存的内容)调用操作系统设置的相应异常处理函数。
  • 操作系统中的相应异常处理函数开始执行,
  • 在异常处理完成后,操作系统会恢复应用程序的上下文。
  • 执行 eret(异常返回,Exception Return)指令以恢复 CPU 自动保存的 EL0 状态(包括 PC 和 SP 等)
  • 并切回到 EL0,使应用程序从被中断处继续执行。

寄存器

在 AArch64 中,有 31 个 64 位通用寄存器,被命名为 X0~X30。其中,

  • X29 用作帧指针(Frame Pointer, FP)寄存器,用于保存函数调用过程中栈顶的地址
  • X30 用作链接指针(Link Pointer, LP)寄存器,因为 CPU 在执行函数调用指令 bl 时会自动把返回地址保存在其中。

物理内存与CPU缓存

CPU 使用物理内存的方式很简单:通过总线向物理内存发送一个读写请求,其中包含目标地址(若是写请求,则还包括写入值),物理内存收到请求后进行读写操作(若是读请求,则将读取值发回 CPU)。

但相比于CPU处理的速度,内存访问速度是非常缓慢的。所以在CPU中引入了缓存。

  • 当 CPU 需要向物理内存写入数据的时候,它可以直接写在 CPU 缓存之中
  • 当 CPU 需要从物理内存读取数据的时候,它可以先在 CPU 缓存中查找,如果没找到再去物理内存中获取,并且把取回的数据放入缓存中,以便加快下次读取速度。

在这里插入图片描述

缓存结构

CPU 缓存是由若干个缓存行(cache line)组成的。每个缓存行包括:一个有效位(valid bit),用于表示其是否有效;一个标记地址(tag address),用于标识其对应的物理地址;一些其他的状态信息。

在这里插入图片描述

通常,CPU 以缓存行(常见的是 64 字节)为单位把物理内存中的数据读取到 CPU 缓存中,也就是说即使只需要单个字节的值,该字节对应的缓存行也会全部进入缓存中。同样,将数据写回到物理内存也是以缓存行为单位的。

典型的 CPU 缓存结构如图 2-6 所示。为了通过内存的物理地址找到对应的缓存,物理地址在逻辑上分为 Tag、Set(也称为 Index)以及 Offset 三段。组(Set)与路(Way)是 CPU 缓存的经典概念。物理地址中的 Set 段能表示的最大数目称为组。例如,如果 Set 段的位数是 8,那么对应的 CPU 缓存的组数就是 256(2⁸ = 256)。同一组(即 Set 段相等)下,支持的最大 Tag 数则称为路,即同一组下的缓存行数目。例如,在图 2-6 中,在 Set 相同的情况下,缓存最多支持 4 个不同的 Tag,也就是 4 路。该 CPU 缓存被称为 4 路组相联(4-Way Set Associative)。

在这里插入图片描述

缓存寻址

下面以支持 AArch64 架构的 Cortex-A57 CPU 中的 L1 数据缓存为例,给出 CPU 缓存查找的一般过程。该 CPU 缓存的相关参数如下:

  • 物理地址的长度为 44 位;
  • 缓存大小为 32 KB,缓存行大小为 64 字节;
  • 256 组,2 路组相联缓存。

假设要读取以物理地址 0x2fbbc030 开始的 4 字节的物理内存数据。首先计算offset、set、tag的位数:

  • **Offset:**CPU使用字节寻址,offset = log2(64) = 6位
  • **Set:**set与组数相关联,set = log2(256) = 8位
  • **Tag:**物理地址为44位,tag = 44- 8 - 6= 30位,由于 0x2fbbc030共32位,所以进行高位补零

得到Tag 为 0xbee f,Set 为 0x0,Offset 为 0x30(十进制为 48)。

根据 Set 定位到 Set = 0 的两个缓存行,对比 Tag 并且检查 Valid 是否为 1(表示该缓存行有效),即可进一步根据 Offset 进行访问。在本例中取出的 4 字节字为 23。如果在寻址过程中,虽然 Set 和 Tag 都匹配上了,但是 Valid 为 0,那么该缓存行是无效的。此时,该物理地址的数据将通过内存进行访问。

在这里插入图片描述

由于软件的运行通常具有局部性(包括时间局部性和空间局部性),因此缓存能够有效提升 CPU 访问物理内存数据的性能;另外,操作系统和应用程序也可以根据 CPU 缓存的特点对代码实施优化,从而更好地利用缓存以提升性能。

设备与中断

内存映射输入输出

内存映射输入输出(Memory-Mapped I/O, MMIO)是一种常见的 CPU 控制和访问设备的方式。MMIO 的原理是:把输入输出设备和物理内存放到同一个地址空间,为设备内部的内存和寄存器也分配相应的地址。

轮询与中断

轮询是由CPU主动周期性查询外部设备状态的机制,适合低优先级、不频繁的事件处理,但效率较低,会消耗CPU资源。

中断是由外部设备主动触发信号中断CPU当前任务,转而执行中断服务程序,适合高优先级、高实时性的事件处理,效率较高,可避免CPU空转。

MMIO 使得 CPU 可以主动地访问设备,中断使得设备能够主动地通知 CPU,这两种机制是 CPU 与设备之间交互的重要方式。

http://www.xdnf.cn/news/19543.html

相关文章:

  • 卷积神经网络中的两个重要概念——感受野receptive filed和损失函数loss function
  • 【Element Plus `el-select` 下拉菜单响应式定位问题深度解析】
  • 刘洋洋《一笔相思绘红妆》上线,献给当代痴心人的一封情书
  • CUDA编程11 - CUDA异步执行介绍
  • Java 不支持在非静态内部类中声明静态 Static declarations in inner classes are not supported异常处理
  • elasticsearch中文分词器analysis-ik使用
  • Uniapp 生命周期详解:页面生命周期 vs 应用生命周期(附实战示例)
  • 大模型应用开发面试实录:LLM原理、RAG工程与多Agent场景化落地解析
  • gh-pages部署github page项目
  • DAY 20 奇异值SVD分解-2025.9.1
  • 计组(2)CPU与指令
  • (ssh客户端)远程连接工具windterm使用教程(ssh工具、远程工具)
  • MiniCPM-V-4.5:重新定义边缘设备多模态AI的下一代视觉语言模型
  • 飞腾2000+/64核 PCIE扫描异常问题排查
  • COM组件——ServicedComponent 类
  • 【架构师干货】系统架构设计
  • Vue3 + MQTT + 高德地图 实现车辆在线状态与实时位置更新
  • 云手机和云游戏之间有着哪些区别?
  • qData 数据中台【开源版】发布 1.0.4 版本,全面升级数据清洗与资产管理能力
  • 使用LoadBalancer替换Ribbon(五)
  • 使用C#语言 基于FTP协议进行文件夹上传下载
  • ansible知识点总结1
  • C/C++ Linux系统编程:进程通讯完全指南,管道通讯、共享内存以及消息队列
  • Linux之Docker虚拟化技术(三)
  • nacos微服务介绍及环境搭建
  • Oracle 查询有哪些用户 提示用户名密码无效
  • AI 入门指南:从 “听不懂人话” 到 “比你懂你”,人工智能到底是个啥?
  • shell编程 函数、数组与正则表达式
  • 网络与信息安全有哪些岗位:(13)安全服务工程师 / 顾问
  • pip不是内部或外部命令的问题怎么解决?