存储系统

 : jank    :   : 634    : 2021-05-19 23:49  操作系统和网络

       

          

存储系统

      一个简单的系统模型,cpu执行指令而存储器系统则为cpu存放指令,在简单模型中,存储器系统是一个字节数组, 实际上整个存储器系统是由层次的结构组成。

        作为一个程序员我们需要理解存储器的层次结构:

                cpu寄存器: 0个周期

            高速缓存: 4~75个周期

            主存: 上百个周期

             磁盘:几千万个周期

        通常离cpu越近的越贵速度越快。

         通常存储技术有: SRAM存储器、DRAM存储器、ROM存储器、机械硬盘、固态硬盘。

               

一、随机访问存储器

      随机访问存储器 Rands Access Memory,缩写:RAM ,通常在内存中使用。

       所谓随机存取,指的是当存储器中的数据被读取或写入时,所需要的时间与这段信息所在的位置或所写入的位置无关。当RAM处于正常工作时,可以从RAM中读出数据,也可以往RAM中写入数据。与ROM相比较,RAM的优点是读/写方便、使用灵活,特别适用于经常快速更换数据的场合。 

       随机访问存储器(RAM)分为两类: 静态(SRAM)和动态(DRAM),SRAM DRAM 更快,也更贵,SRAM通常用来做高速缓存(CPU片上、片下均支持),DRAM用来做主存。SRAM通常只有几Mb,而DRAM可以有成千上万Mb。这两类存储器断电均会丢掉信息。

                      

 1.1 SRAM 

       SRAM将每个位存储在一个双稳态的(bistable)存储单元里。每个单元使用4~6个晶体管电路实现(晶体管电路,)这个电路可以无限期地保持两个不同电压配置或状态之一。SRAM不像DRAM一样需要不断刷新,而且工作速度较快,但由于存储单元器件较多,空间占用较大,不适合做更大的存储。如果用高频率访问SRAM,其功耗比DRAM大得多,如果低频访问功耗极低。

 1.2 DRAM

          DRAM 将每个位存储为对一个电容(很小,约30毫微微法拉)的充电。DRAM很容易受干扰,DRAM单元在10~100毫秒内失去电荷,幸运的是计算机运行的时钟周期通常以纳秒衡量。内存系统必须周期性的通过读出然后重写来刷新内存的每一位。

       DRAM需要连接到内存控制器的电路,可以一次传送w位到每个DRAM芯片或一次从每个DRAM芯片传出w位。

        DRAM组织成二维阵列而不是线性数组的一个原因是降低芯片上引脚的数量。

存储层次结构

 

2.1 缓存结构

image.png 

 

 

 

2.2 寄存器

寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果以及一些CPU运行需要的信息. 64CPU是指CPU内部的通用寄存器的宽度为64bit,支持整数的64 bit宽度的算术逻辑运算寄存器由编译器管理

寄存器有多种类型,分别如下:

通用寄存器:程序执行代码最常用、最基础的寄存器,所谓通用,即这些寄存器CPU没有特殊的用途,大部分时间都是应用程序执行过程中操作这些寄存器来实现指令功能,

x86架构CPU走的是复杂指令集(CISC 路线,提供了丰富的指令来实现强大的功能,其中通用寄存器新增加8个有标号的寄存器%r8%r15。加上x86的原有8个,一共16个寄存器,分别是:

%rax%rbx%rcx%rdx%esi%edi%rbp%rsp

%r8%r9%r10,%r11%r12%r13%r14%r15

ax: 通常用来执行加法,函数调用的返回值一般也放在这里面

bx: 数据存取

cx: 通常用来作为计数器,比如for循环

dx: 读写I/O端口时,dx用来存放端口号

sp: 栈顶指针,指向栈的顶部

bp: 栈底指针,指向栈的底部,通常用bp+偏移量的形式来定位函数存放在栈中的局部变量

si: 字符串操作时,用于存放数据源的地址

di: 字符串操作时,用于存放目的地址的,和si两个经常搭配一起使用,执行字符串的复制等操作

    disidxcxr8r9 还可以用作函数参数,依次对应第1参数,第2参数。。。

%rbx%rbp%r12%r13%14%15 可以用作数据存储,遵循被调用者使用规则,简单说就是随便用,调用子函数之前要备份它,以防他被修改

%r10%r11 用作数据存储,遵循调用者使用规则,简单说就是使用之前要先保存原值

 

标志寄存器

 标志寄存器,里面有众多标记位,记录了CPU执行指令过程中的一系列状态,这些标志大都由CPU自动设置和修改

指令寄存器

CPU中最最重要的寄存器了,它指向了下一条要执行的指令所存放的地址,CPU的工作其实就是不断取出它指向的指令,然后执行这条指令,同时指令寄存器继续指向下面一条指令,如此不断重复,这就是CPU工作的基本日常。

漏洞攻击中,黑客想尽办法费尽心机都想要修改指令寄存器的地址,从而能够执行恶意代码。

 

段寄存器CPU的内存寻址技术紧密相关

控制寄存器:存储CPU运行过程中自身的一些关键信息

调试寄存器:支持软件的调试,主要是针对C/C++等‘底层’编程语言

描述符寄存器描述符,其实就是一个数据结构,用来记录一些信息,‘描述’一个东西。把很多个描述符排列在一起,组成一个表,就成了描述符表。再使用一个寄存器来指向这个表,这个寄存器就是描述符寄存器任务寄存器

MSR寄存器x86架构CPU,内部增加了一组新的寄存器,统称为MSR寄存器,中文直译是模型特定寄存器,意思是这些寄存器不像上面列出的寄存器是固定的,这些寄存器可能随着不同的版本有所变化。这些寄存器主要用来支持一些新的功能。

随着x86CPU不断更新换代,MSR寄存器变的越来越多,但与此同时,有一部分MSR寄存器随着版本迭代,慢慢固化下来,成为了变化中那部分不变的,这部分MSR寄存器,Intel将其称为Architected MSR,这部分MSR寄存器,在命名上,统一加上了IA32的前缀。

这里选取三个代表性的MSR简单介绍一下:

IA32_SYSENTER_CS

IA32_SYSENTER_ESP

IA32_SYSENTER_EIP

这三个MSR寄存器是用来实现快速系统调用。

在早期的x86架构CPU上,系统调用依赖于软中断实现,类似于前面调试用到的int 3指令,在Windows上,系统调用用到的是int 2e,在Linux上,用的是int 80。

软中断毕竟还是比较慢的,因为执行软中断就需要内存查表,通过IDTR定位到IDT,再取出函数进行执行。

系统调用是一个频繁触发的动作,如此这般势必对性能有所影响。在进入奔腾时代后,就加上了上面的三个MSR寄存器,分别存储了执行系统调用后,内核系统调用入口函数所需要的段寄存器、堆栈栈顶、函数地址,不再需要内存查表。快速系统调用还提供了专门的CPU指令sysenter/sysexit用来发起系统调用和退出系统调用。

64位上,这一对指令升级为syscall/sysret。

 

 

 

 

2.3 高速缓存

CPU高速缓存是为了解决CPU速率和主存访问速率差距过大问题。高速缓存目前分为L1(32K)L2(>256K)L3 (nM)层缓存。L1L2cpu独享L3多个cpu共享

计算机程序运行遵循局部性原则,即在一段时间内,整个程序的执行仅限于程序中的某一部分。局部性表现为时间局部性和空间局部性。

时间局部性  cache保存近期被访问的数据。

空间局部性  cache从主存中取回数据时,会取回与位置相邻的主存单元数据。以数据块(block, cache line)为单位和主存进行数据交换。

 

地址映射为了把信息放到Cache中,必须应用某种函数把主存地址定位到Cache中。在信息按这种映射关系装入CacheCPU执行程序时,会将程序中的主存地址变换成Cache地址这种操作称为地址变换

在高速缓存有三种映射策略:直接映射、全关联映射、组相联映射

1.全相联方式

地址映象规则:主存的任意一块可以映象到Cache中的任意一块

(1) 主存与缓存分成相同大小的数据块。

(2) 主存的某一数据块可以装入缓存的任意一块空间中。如果Cache的块数为Cb,主存的块数为Mb,则映象关系共有Cb×Mb种。

目录表存放在相关(联)存储器中,其中包括三部分:数据块在主存的块地址、存入缓存后的块地址、及有效位(也称装入位)。由于是全相联方式,因此,目录表的容量应当与缓存的块数相同。

优点:命中率比较高,Cache存储空间利用率高。

缺点:访问相关存储器时,每次都要与全部内容比较,速度低,成本高,因而应用少。

2.直接相联方式

地址映象规则: 主存储器中一块只能映象到Cache的一个特定的块中。

(1) 主存与缓存分成相同大小的数据块。

(2) 主存容量应是缓存容量的整数倍,将主存空间按缓存的容量分成区,主存中每一区的块数与缓存的总块数相等。

(3) 主存中某区的一块存入缓存时只能存入缓存中块号相同的位置。

主存中各区内相同块号的数据块都可以分别调入缓存中块号相同的地址中,但同时只能有一个区的块存入缓存。由于主、缓存块号相同,因此,目录登记时,只记录调入块的区号即可。主、缓存块号及块内地址两个字段完全相同。目录表存放在高速小容量存储器中,其中包括二部分:数据块在主存的区号和有效位。目录表的容量与缓存的块数相同。

优点:地址映象方式简单,数据访问时,只需检查区号是否相等即可,因而可以得到比较快的访问速度,硬件设备简单。

缺点:替换操作频繁,命中率比较低。

3.组相联映象方式

组相联的映象规则:

(1) 主存和Cache按同样大小划分成块。

(2) 主存和Cache按同样大小划分成组。

(3) 主存容量是缓存容量的整数倍,将主存空间按缓冲区的大小分成区,主存中每一区的组数与缓存的组数相同。

(4) 当主存的数据调入缓存时,主存与缓存的组号应相等,也就是各区中的某一块只能存入缓存的同组号的空间内,但组内各块地址之间则可以任意存放,即从主存的组到Cache的组之间采用直接映象方式;在两个对应的组内部采用全相联映象方式。

主存地址与缓存地址的转换有两部分,组地址是按直接映象方式,按地址进行访问,而块地址是采用全相联方式,按内容访问。组相联的地址转换部件也是采用相关存储器实现。

优点:块的冲突概率比较低,块的利用率大幅度提高,块失效率明显降低。

缺点:实现难度和造价要比直接映象方式高。

 

主存地址有m位,共有M=2^m个不同地址;高速缓存分成S个组,每个组E行,每行B个字节,每行由一个 B=2^b字节的数据块组成,一个有效位指明这个行是否包含有意义信息,还有t=m-(b+s)个标记位(tag bit)用于唯一标识存储在这个高速缓存行中的块。缓存总大小为C=BxExS。这种缓存结构被称为:组相联高速缓存

E等于1的时候称之为直接映射高速缓存

E等于C/B即一个组包含所有行的时候称之为全相联高速缓存

CPU缓存与主存交换数据每次大小是固定的,我们称其为cpu cache line,在64位系统下通常是64字节,比如nginx中存储http headerhash表。假设我们的cache size64字节,而一个hash bucket48字节。假如某一个bucket的起始地址是1F7D030,那么它占用的内存就从1F7D0301F7D05F,而cache size的特性导致只会从64的整数倍地址访问,于是需要访问两次:1F7D0001F7D040。而如果我们能使得hash bucket大小是cache size的整数倍,那么就不会出现访问一个hash bucket需要两次操作主存的情况。比如,若原本bucket size32,则设为64;原本为96,则设为128,即向上对齐。nginx有一个向上对齐函数就是做这个事的.

 image.png

 

 

 缓存读过程:

cpu在读数据的过程,不会直接去主存中读取数据,会先把指令发给cache一层一层的找),如果cache中没有命中,cache会把相应的指令发给主存,并且以cache line的方式读取并保存在cache,一个高速缓存可以用一个四元组来表示(S, E, B, m),m表示计算机的位数。拿Core i7L1缓存来说,S = 64E = 8B = 64, m = 64,可以表示为(64,8,64,64)

 

 

cache 读数据过程,主要分三步:

第一步组选择 64位内存地址为例,有64个组,那么64位的内存地址中就要拿出s=6(000000-111111)来表示64个组号,根据这个内存地址的s位定位到一个组。

第二步行匹配:每个组有8行,大小为64B的块得到的b=6, 计算得到t = m - (b+s) = 64 - 12 = 52,也就是说64位地址的高52位作为t,用这个t标记去这个组的8个行去匹配对应t标记位,如果有匹配的行,就命中,否则不命中。

 

第三步字选择:如果命中,再由这个内存地址的低b位计算出这个地址在块中的偏移位置。块可以理解为一个字节数组,64个字节的块就有块[0]....[63]个偏移量,有内存地址的低b位可以计算得到这个地址对应的偏移量,从而找到这个数

 

 

 image.png

缓存写

    写策略

    1.直接写( Write through ) : 在数据更新时,将数据同时写入内存和Cache,该策略操作简单,但是因为每次都要写入内存,速度较慢

    2.回写(Write back):

    分配策略:当一个缓存块需要被替换回内存时,才将其内容写入内存。如果快取命中,则总是不用更新内存。为了减少内存写操作,缓存块通常还设有一个脏位(dirty bit),用以标识该块在被载入之后是否发生过更新。如果一个缓存块在被置换回内存之前从未被写入过,则可以免去回写操作。

 

1.按写分配(Write allocate:是指,先如处理读失效一样,将所需数据读入缓存,然后再将数据写到被读入的单元。

2.不按写分配(No-write allocat): 则总是直接将数据写回内存。

 

image.png 

L1L2缓存在CPU核内部独有,L1D-cache(数据) 和 I-cache(指令)。

多核共享L3 cache

 

缓存一致性

多个CPU对某块内存同时读写,就会引起冲突的问题,被称为Cache一致性问题。

有这样一种情况:

a. CPU1读取了一个字节offset,该字节和相邻的数据就都会被写入到CPU1Cache.

b. 此时CPU2也读取相同的字节offset,这样CPU1CPU2Cache就都拥有同样的数据。

c. CPU1修改了offset这个字节,被修改后,这个字节被写入到CPU1Cache中,但是没有被同步到内存中。

d. CPU2 需要访问offset这个字节数据,但是由于最新的数据并没有被同步到内存中,所以CPU2 访问的数据不是最新的数据。

这种问题就被称为Cache一致性问题,MESI协议为了解决这个问题而生,当一个CPU1修改了Cache中的某字节数据时,那么其它的所有CPU都会收到通知,它们的相应Cache就会被置为无效状态,当其他的CPU需要访问此字节的数据时,发现自己的Cache相关数据已失效,这时CPU1会立刻把数据写到内存中,其它的CPU就会立刻从内存中读取该数据。

MESI协议是通过四种状态的控制来解决Cache一致性的问题:

M:代表已修改(Modified) 缓存行是脏的(dirty),与主存的值不同。如果别的CPU内核要读主存这块数据,该缓存行必须回写到主存,状态变为共享(S.

E:代表独占(Exclusive) 缓存行只在当前缓存中,但是干净的(clean--缓存数据同于主存数据。当别的缓存读取它时,状态变为共享(S);当前写数据时,变为已修改(M)状态。

S:代表共享(Shared) 缓存行也存在于其它缓存中且是干净(clean)的。缓存行可以在任意时刻抛弃。

I:代表已失效(Invalidated) 缓存行是脏的(dirty),无效的。

四种状态的相容关系如下:

image.png 

 

三、主存

主存(Main memory)即电脑内部最主要的存储器也称内存,用来加载各式各样的程序与资料以供 CPU 直接运行与运用。 DRAM 性价比很高,且扩展性也不错,是现今一般电脑主存的最主要部分

 

电脑运行时,电脑的主内存按照被使用情况可分类为:

可利用(Available)物理内存:可立即分配给程序使用的内存。包括:

空闲(Free)物理内存:完全未被使用,内容为全 0

缓存(Cached)物理内存

备用(standby)物理内存:操作系统预先把可能要用到的硬盘数据加载所占用的内存,还没被用户进程所使用,因此可随时丢弃从新初始化为 0

已修改(modified)物理内存:已被修改过的 caching 用途的内存,可在任意时刻写回硬盘文件(不是分页文件)然后被重用。由于硬盘 I/O,已修改(modified)物理内存不能计入空闲(Free)物理内存

被使用(used)物理内存:已经被进程使用的内存

用户进程使用的物理内存,即工作集Working set)。Working Set 包含了可能被其他程序共享的内存,例如DLL。所以所有进程的Working Set加起来有可能大于实际的被使用(used)的物理内存。Private Bytes 是只被本进程提交(commit)的虚拟地址空间,不包括其他进程共享的内存。Virtual Byte 是整个进程占用的全部虚拟地址空间。32 Windows 用户模式下,进程最大可以使用 2GiB,可以通过修改 Boot.ini 文件扩展为最大可以使用到 3GiB任务管理器中的 Memory Usage 对应的是 working setVM Size 对应的是 private bytes

核心进程使用的物理内存

分页的核心进程使用的物理内存:可以交换到分页文件中,从而可被回收的物理内存

未分页(Non paged)的核心进程使用的物理内存:不能交换到分页文件的内存,总是要保留在物理内存中

硬件保留(hardware reserved)的物理内存:被 CPU 中的 GPU 核心或者其他外设硬件占用的,不由操作系统使用的内存

 

 

、磁盘存储

       只读存储器(Read Only Memory) 缩写:ROM , 即使可读可写也统称为ROM,从磁盘上读取信息为毫秒级,比DRAM10万倍,比SRAM100万倍。

 4.1 磁盘构造

           磁盘是由盘片(platter)构成,每个盘片有两面称为表面(surface),覆盖着磁性记录材料,盘片中央有一个可旋转的主轴,使盘片以固定的旋转速率(rotational rate)旋转,通长是5400~15000转每分钟(Revolution Per Minute RPM),磁盘可以有多个盘片。

          表面是由一组称为磁道的同心圆组成,每个磁道有一组扇区(sector),每个扇区包含数据相等的数据位(512字节),数据编码在扇区上的磁性材料中。扇区之间的间隙(gap)不存储数据位,存储标识扇区的格式化位。(每个磁道的扇区数一样是说的老的硬盘,外圈的密度小,内圈的密度大,每圈可存储的数据量是一样的。新的硬盘数据的密度都一致,这样磁道的周长越长,扇区就越多,存储的数据量就越大。)

       磁盘容量计算公式:

     磁盘容量=字节数(扇区)* 平均扇区数(磁道)* 磁道数(表面)*表面数(盘片)*盘片数(磁盘)

 

image.png 

 

 

      磁盘控制器为了对操作系统隐蔽磁盘的复杂性现代磁盘将其呈现成一个B个扇区大小的逻辑块序列编号为01。。。B-1而磁盘控制器维护着逻辑块号和实际物理磁盘扇区之间的映射关系磁盘控制器收到来自cpu的读命令后将读取的块号翻译成三元组盘面磁道扇区),然后将读/写头移动到柱面等待扇区移动到读/写头下将读写头感知到的位放在控制器的缓冲区然后将它复制到内存中期间不需要CPU的干涉可以自行读/称为直接内存访问Direct Memory AccessDMADMA完成后磁盘控制器通过发送一个终端信号到CPU芯片的一个外部引脚上来通知CPU这会导致CPU暂停当前任务跳转到一个操作系统例程这个程序记下I/O已完成然后将控制器返回CPU中断的地方

4.2 固态硬盘

固态硬盘Solid State Disk SSD是一种基于闪存技术的硬盘

一个SSD封装由一个或多个闪存芯片和闪存翻译层组成一个闪存芯片由B个块的序列组成每个块32128P512byte4KB组成数据是以页为单位读取的只有在页所属的整块被擦除100000次损坏后才能写这一页一旦一个块被擦除块中的其他页写时可以不用再擦除

相比磁盘有如下优缺点

随机访问时间比磁盘块

由半导体存储器构成能耗低结实

 缺点

    相对磁盘要贵但慢慢在便宜

    闪存块会磨损相对容易坏

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


   

备案编号:赣ICP备15011386号

联系方式:qq:1150662577    邮箱:1150662577@qq.com