Fork me on GitHub

深入浅出计算机组成原理——原理篇:存储与I/O系统(40-45)

全文内容主要来自对课程《深入浅出计算机组成原理》的学习笔记。

40 | 理解内存(上)

虚拟内存地址究竟是怎么转换成物理内存地址?

简单页表

页表(Page Table):虚拟内存里面的页,到物理内存里面的页的一一映射。

一个内存地址分成页号(Directory)和偏移量(Offset)。

一页内存在物理层面是连续的,一般大小是 4K 字节(4KB),需要 20 位的高位,12 位的低位。

内存地址转换步骤

  1. 虚拟内存地址,切分成页号、偏移量;
  2. 从页表,查询对应的物理页号;
  3. 物理页号+偏移量,就是物理内存地址。

页表空间

32位地址,高位有20,需要记录$2^{20}$个物理页号的映射,数组形势,一个页号4字节,总计大约4MB。看上去不多,但如每个进程有一份,就很大了。

多级页表

只需要去存用到的页之间的映射关系。

虚拟内存占用的地址空间,通常是两段连续的空间,多级页表(Multi-Level Page Table)适用这类。

如上图,一个4级多级页表:

  1. 页号部分(20位)拆成4段(每段5位),对应各级页表索引;
  2. 每级索引对应的是下一级页表的位置;
  3. 最后的1级页表,继续用“页号 + 偏移量”来获取物理内存地址。

因为实际的虚拟内存空间通常是连续的,所以需要的 2、3 级页表很少。

看下空间大小:

  • 每段索引5bit,1 级页表有$2^5=32$个条目映射,每个条目 4 字节(32bits=4Bytes),该 1 级页表总计 128 字节;
  • 每个 1 级索引表映射 32 个 4KB 内存快,即 128Kb;
  • 那么每个填满的2级索引表,对应 32 个 1 级索引表,总计 4MB 内存映射。

需要存的映射少了,空间节省了,但查询次数多了,一个典型的时间换空间的方案。


41 | 理解内存(下)

  • 地址转换是很高频,怎么解性能问题?
  • 数据、指令都在内存,怎么解内存安全问题?

加速地址转换:TLB

内存访问其实比 Cache 要慢,简单的内存转换,1次变4次。解法:加缓存。

这块缓存芯片我们称之为 TLB,全称是地址变换高速缓冲(Translation-Lookaside Buffer)。

和 CPU 里的高速缓存类似,用脏标记来实现“写回”等缓存管理策略。为了性能,整个内存转换过程也要由硬件来执行,封装为内存管理单元(MMU,Memory Management Unit)芯片

安全性与内存保护

可执行空间保护

一个进程使用的内存,指令部分设置成“可执行”的,数据等其他部分不给予“可执行”的权限。

地址空间布局随机化

核心问题:其他的人、进程、程序,会去修改掉特定进程的指令、数据,然后,让当前进程去执行这些指令和数据,造成破坏。

原进程内存空间是固定,容易获取指令位置。地址空间布局随机化之后,无法猜到指令的内存地址,随意修改只会让程序 crash 掉,不会执行危险代码。

一个经典的随机性应用:
用户名称+密码通过hash保护,但泄露太多加密的,容易通过彩虹表等方式推测结果。于是,在hash的时候全部加上盐值(Salt),即使猜出来也无法使用。


42 | 总线

CPU 和内存、以及外部输入输出设备的通信,计算机是怎么完成的?

降低复杂性

假设计算机有 N 个不同的设备需要通信,并且是单独链接,那么复杂度就是 $N^2$。

优化的方案:不用单独通信,都是用一条公用线路,即总线

总线,就是一组线路,英文是 BUS,设计模式是事件总线
事件总线:

  • 发布者:各模块触发对应的事件,并把事件对象发送到总线上;
  • 监听者:各模块也注册到总线上,去监听事件,并根据对象类型或内容来决定是否要处理或者响应。

理解总线

双独立总线(Dual Independent Bus,缩写为 DIB):

  • 快速的本地总线(Local Bus);
  • 较慢的前端总线(Front-side Bus)。

CPU链接前端总线,即系统总线,与 I/O 桥接器相连,分别连接内存总线和 I/O 总线。

总线通常有三类线路:

  • 数据线(Data Bus),传输数据;
  • 地址线(Address Bus),数据传输的位置,是内存的某个位置,还是某 I/O 设备。
  • 控制线(Control Bus),用来控制对于总线的访问。

43 | 输入输出设备

接口和设备

输入输出设备一般2个部分:

  • 接口(Interface);
  • 实际的 I/O 设备(Actual I/O Device)。

三类寄存器(在设备的接口电路上):

  • 状态寄存器(Status Register);
  • 命令寄存器(Command Register);
  • 数据寄存器(Data Register)。

控制 I/O 设备

设备接口上除了3类寄存器,还有控制电路来控制实际硬件。

  1. 数据寄存器(Data Register)。

    CPU 向 I/O 设备写入需要传输的数据。实际上还有数据缓冲区。

  2. 命令寄存器(Command Register)。

    CPU 发送打印命令给打印机。控制电路两个动作:状态寄存器把状态设置成 not-ready;操作打印机进行打印。

  3. 状态寄存器(Status Register)。

    告诉 CPU 设备已在工作,其他数据和命令不能执行。直到完成,重新 ready 状态。

信号和地址

CPU 往总线上发送的命令具体是什么,才能和 I/O 接口上的设备通信呢?

答案是机器指令。但 MIPS 并没有专门的 I/O 指令,实际上是使用内存地址

主内存会映射 I/O 设备的内存地址。CPU 通信时,往这些地址发送数据即可。这种叫内存映射 IO(Memory-Mapped I/O,简称 MMIO)。

Intel CPU 既支持 MMIO,还可以通过特定的指令,来支持端口映射 I/O(Port-Mapped I/O,简称 PMIO)。核心的区别,PMIO 里面访问的设备地址,不再是在内存地址空间里面,而是一个专门的端口(Port)。


44 | 理解IO_WAIT

并不是所有问题都能靠利用内存或者 CPU Cache 做一层缓存来解决。硬盘使用还是很多的,尤其是大数据场景,那么硬盘的 I/O 性能就很重要。

IO 性能、顺序访问和随机访问

硬盘厂商的性能报告:

  • 响应时间;
  • 数据传输率。

硬盘:

  • HDD:机械硬盘,SATA 3.0 接口。
  • SSD:固态硬盘,SATA 3.0 & PCI Express 接口。

SATA 3.0,带宽 6Gb/s,“b”是bit,则约768MB/s($6 \times 1024 / 8 = 768$)。但日常约 200 MS/s。
SSD 大约 500 MB/s,如果换成 PCI Express 约 2 GB/s。

响应时间,HDD 约十毫秒左右,SSD 约几十微妙,差异更大。但,无论哪个,貌似性能还可以,与实际经验不符合。

在顺序读写和随机读写的情况下,硬盘的性能是完全不同的

IOPS:每秒输入输出操作的次数,去随机读取磁盘上某一个 4KB 大小的数据,一秒之内可以读取到多少数据。

SSD,随机读写约 40MB/s,即1万次 4KB 数据,即 IOPS。写入的话约90MB/s,IOPS 约2万。
而HDD,IOPS 大约为100。

定位 IO_WAIT

CPU 的主频通常在 2GHz 以上,也就是每秒可以做 20 亿次操作。即使一条读写指令,需要很多个时钟周期,硬盘完全跟不上。

通过 top 和 iostat 这些命令,一起来看看 CPU 到底有没有在等待 io 操作。

top 去看服务的负载,也就是 load average。也可以看 CPU 是否在等待 IO 操作完成。

以 %CPU 开头的行,有一个叫作 wa 的指标,这个指标就代表着 iowait

如果 iostat 很大,可以通过 iostat 查看实际硬盘读写。

其中, tps 指标,其实就对应着我们上面所说的硬盘的 IOPS 性能。而 kB_read/s 和 kB_wrtn/s 指标,就对应着我们的数据传输率的指标

iotop命令找哪一个进程是这些 I/O 读写的来源。

通过stress -i 2,模拟两个进程往硬盘写数据。top 的输出里面,CPU 就有大量的 sy 和 wa。通过 iostat,里面的 tps 很快就到了 4 万左右。iotop, I/O 占用都来自于 stress 产生的两个进程了。


45 | 机械硬盘

拆解机械硬盘

前面提过,机械硬盘 IOPS 大约100,这个的原理是什么?

机械硬盘三个组成部分:盘面、磁头和悬臂。

盘面(Disk Platter):实际存储数据的,跟光盘类似,铝、玻璃或者陶瓷制成,上有磁性涂层来存储数据。中间有转轴控制转速,RPM(Rotations Per Minute)一般为7200,每秒则120转。

磁头(Drive Head):从盘面读取数据传输给电路,一个硬盘会有多个堆叠的磁盘,每个磁盘正反面都会各有一个磁头。

悬臂(Actutor Arm):链接磁头,用来定位磁头到磁道的。

磁盘会切分不同半径的同心环作为磁道,每个磁道会分成多个扇区,上下不同磁盘但平行的扇区称为一个柱面。所以读取的数据的时候,悬臂需要控制磁头,移动到对应的磁道上,并且盘面需要转转道对应位置,如此磁头才能读取到指定的扇区/柱面。

硬盘上的随机访问:

  • 平均延时(Average Latency):盘面旋转,把几何扇区对准悬臂位置的时间。

    7200转/min 硬盘,即 240半圈/s,寻找指定扇区平均需要半圈距离,即 1s / 240 = 4.17ms。

  • 平均寻道时间(Average Seek Time):盘面旋转,悬臂定位到扇区的的时间。

    一般在 4-10ms

综上,随机访问时间约8-14ms,对应的 IOPS 为 125-70.

Partial Stroking

提升 HDD 硬盘效率的一个办法就是提高转速,这是很多厂商历史做的事情。

还有一种,空间换时间的方法,来提高硬盘的IOPS,就是 Partial Stroking 或者 Short Stroking

一般硬盘的寻道时间都比平均延时要长,如果消除这部分,可以有效提高 IOPS。那就是磁头仅仅用最外道的磁道,或者只用1/4磁道。

不过这是当年互联网蓬勃发展时,工程师们想要改善性能问题的有偿解法。


-------------本文结束感谢您的阅读-------------

本文标题:深入浅出计算机组成原理——原理篇:存储与I/O系统(40-45)

文章作者:

原始链接:https://www.xiemingzhao.com/posts/computerOrgArc40to45.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。