计算机主存和外存设备的工作原理

计算机主存和外存设备的工作原理

摘要
计算机存储单元的组成,存储空间计算、编址与寻址、数据读写。

引言

计算机知识很枯燥,也不易理解。计算机历史充满着趣味和智慧,我们可以通过了解这背后的缘由,加深自己对其的认知和记忆。

计算机存储

这篇仅讨论内存(主存)和外存设备。

存储单元

我们知道计算机使用电子元器件电压范围来判断是高是低,或使用磁化物质极性记录信息,而这些信息也就是我们说的“1”和“0”。一个元器件表示2种状态,计算机定义为一个bit有“1”和“0”两种取值。

计算机中规定8bits1byte。字节byte的历史定义1,指能够用于编码单个字符所需要的bit数量。

那为什么不是7bits或者9bits呢?历史上确实出现了非8bits的定义标准2,不同的计算机标准,1byte不一定等于8bits。但最终都被筛选淘汰掉了。,现如今我们认为1byte=8bits

也就是说,我们1byte就足以表示单个字符。

存储空间计算

假设1个存储单元就是1byte,可以表示2^8 = 256种状态,表示256个字符。

1 KiloBytes = 2^10 Bytes,1千字节
1 MillBytes = 2^20 Bytes,1兆字节
1 GigaBytes = 2^30 Bytes,1吉字节
1 TeraBytes = 2^40 Bytes,1钛字节
1 PetaBytes = 2^50 Bytes,1拍字节
1 ExaBytes = 2^60 Bytes,1艾字节
1 ZettaBytes = 2^70 Bytes,1泽字节
1 YottaBytes = 2^80 Bytes,1尧字节

这里1个Byte意味着8个电子元器件,不考虑电路其他元件的话。

典型存储单元大小

通常主存设备也就以1byte来作为最小的存储单元。

实际产品中,存储单元的大小由产品硬件设计决定。
如果定义存储单元大小为512Bytes,即使是32位-4字节的地址总线,也能支持2^32*512Bytes=2TB存储空间。比如机械磁盘的寻址单元(最小存储单元),称之为扇区,就是512Bytes

常见外设存储设备的存储单元大小:

  • 机械磁盘:512Bytes,扇区作为最小存储单元。

  • SSD固态磁盘:SSD的最小存储单元是1page,是由一组颗粒组成。每个颗粒(cell)可以是1bit2bits3bits甚至4bits,典型的1page4KB,常提及的4KB对齐就是这么来的,也即最小存储单元是4KBNTFS默认最小分配单元正好4KB,或者使用4KB的任何整数倍。需要说的是SSD在擦除数据的时候,不是以page为单位,而是以多个page组成的块(Block)为单位。

  • U盘:闪存的一种,一般使用建议的最小存储单元,通常是4KB。而且U盘不建议使用NTFS格式文件系统(“日志式”,需要记录详细的读写操作),因为要不断读写比较伤闪存芯片。一般用FAT32exFAT(支持>4GB的单个文件操作)。

编码

CPU中输入数据(转换后的电平信号)经过设计好的电路实现逻辑和算术运算,运算结果输出到电子元器件电压状态或者组合电子元器件的电压状态(电平信号)。保持这个元件的状态后,然后可以将这些结果数据固化到磁盘、SSD、U盘等外存设备。

输入和输出数据在计算机看来都是电平信号,它是怎么和我们的字符、文字相对应起来的呢?

这里就用到了一种映射的概念,计算机称之为编码。读者应该查找编码相关资料文档,进行了解。这里推荐一篇文章,可以帮助我们系统性地理解编码:字符编码的前世今生——一文读懂字符编码

  • 我们键盘输入字符,在保存的时候,操作系统会以用户指定或者默认的编码方式查对应编码表将字符编码成二进制数据,并写入存储器保存。
  • 输出的结果数据,或者打开保存的文本时,操作系统根据编码方式,查找对应的编码表将二进制数据解码,然后绘制显示在屏幕上。

如果没有指明文件编码,操作系统编辑默认行为存在差异,比如在Windows系统上默认地区编码(中国-GBK,page 936)读写文件,Linux系统(UTF8)或其他系统打开,可能出现乱码。GBK以2个字节编码汉字,UTF8以3个字节编码汉字,因此相同内容不同编码占用大小是不一样的。但是UTF8是国际统一编码,更不容易乱码。UTF-8 with BOM在文档头插入了0xEF 0xBB 0xBFUnicode字节顺序标记。如果使用UTF8编码,一定要使用without BOM的标准编码方式。

点击访问unicode官网

需要说的是,我们看到的文字、数字、字符、图片、视频,听到的音频等,在计算机看来都是数字信号,通过编码的方式存入存储设备,通过解码的方式转换为我们看到的或听到的。解码后让我们能看到需要计算机发送数据给屏幕进行绘制,让我们听到需要发送数据给音频设备播放。

编址与寻址

读写存储设备的前提是能准确定位指定的位置,更确切地说,颗粒度定位到某个指定的存储单元。

主存设备

利用编码的思想,我们可以设计一个电路或者功能结构,其功能是只要输入位置编码信息(某种表示状态)就可以唯一确定对应的存储单元。

  • 1个bit有2种组合,可以唯一确定2个存储单元
  • 2个bit有4种组合,可以唯一确定4个存储单元
  • N个bit有2^N种组合,可以唯一确定2^N个存储单元

假设输入有32个电子元器件,那么有2^32种组合,也就是4G个存储单元的空间。
当增加到64个时,可寻址存储单元个数2^64,即2^32 * 4G = 16E

地址总线:Address Bus,可以认为是在CPU访问主存时,提供了这样的一个电路。
如果地址总线宽度为32,则能够唯一确定4G个存储单元,也即4GB,宽度64,则不需要担心主存空间瓶颈的问题。

想象将所有存储单元一字排开,开始给他们依次编号。有了编号就可以找到对应的存储单元。根据我们地址总线的宽度,可以从0开始编号,直到将所有存储单元都完成编号或者超过支持的最大存储空间。这样,当我们在地址总线输入端设置对应的编号数据(对应电平信号)时,电路直接能唯一确定到对应的存储单元。CPU根据命令,经由数据总线读写数据。通常数据总线和地址总线宽度相同,但不绝对。

总之,CPU访问主存时,地址总线宽度N决定了所支持的主存空间大小(2^N个存储单元)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
gh503@gh503-OMEN-by-HP-Laptop:~$ sudo dmidecode -t memory
# dmidecode 3.3
Getting SMBIOS data from sysfs.
SMBIOS 2.8 present.

Handle 0x0016, DMI type 16, 23 bytes
Physical Memory Array
Location: System Board Or Motherboard
Use: System Memory
Error Correction Type: None
Maximum Capacity: 32 GB
Error Information Handle: No Error
Number Of Devices: 2

Handle 0x0017, DMI type 17, 40 bytes
Memory Device
Array Handle: 0x0016
Error Information Handle: No Error
Total Width: 64 bits
Data Width: 64 bits
Size: 16 GB
Form Factor: SODIMM
Set: None
Locator: Bottom-Slot 1(left)
Bank Locator: BANK 0
Type: DDR4
Type Detail: Synchronous
Speed: 2400 MT/s
Manufacturer: Samsung
Serial Number: 0B627394
Asset Tag: 9876543210
Part Number: D471A2K43EB1-CRC
Rank: 2
Configured Memory Speed: 2400 MT/s
Minimum Voltage: 1.35 V
Maximum Voltage: 1.5 V
Configured Voltage: 1.2 V

这里可以看到系统内存最大支持插入32GB,当前插入2块内存,显示其中1块16GB DDR4内存,数据传输速率实际每秒2400
百万次,一次传输数据宽度64bits。

机械硬盘 HDD

也叫磁盘,因为机械硬盘使用的是磁性物质来记录信息。

如果不了解机械硬盘,可以阅读机械硬盘的工作原理一个故事看懂机械硬盘原理

机械硬盘由两种寻址方式:

  • CHS寻址
    使用柱面号(cylinder10bits)、磁头号(head8bits)、扇区号(sector6bits)唯一确定存储某一位置的数据。通过机械的方式获取磁性盘片上的数据。

不考虑机械设计约束,最大寻址空间:2^cylinder_bits * 2^head_bits * 2^sector_bits * sector_size_bytes /1024/1024/1024 GB

  • LBA寻址
    将三维寻址方式转换成一维寻址方式,定义LBA逻辑扇区号
    磁头数 * 每隧道扇区数 * 当前所在柱面号 + 每隧道扇区数 * 当前所在磁头号 + 当前所在扇区号 - 1

通过硬盘控制器,将逻辑地址转换为实际硬盘的物理地址。

最大寻址扇区数:2^ 地址位数-1。

在硬盘或U盘等设备格式化时,可以设定存储单元大小,可以预料到最小存储单元越小,利用率越高,效率越低;而最小存储单元越大,利用率越低,效率反而越高。申请过内存的同学肯定知道,内存空间足够的话,我就不需要再申请了,而且可以一次性写入和读取。

现在机械硬盘使用的LBA寻址。

固态硬盘 SSD

我们都知道固态硬盘速度比机械硬盘快多了,而且没有机械硬盘的噪音,体型小带来的易携带、也不怕振动带来的数据损坏。因为固态硬盘使用的时光学寻址,没有磁头、盘片这些精密部件。而且没有存储单元都有唯一的地址,因此在访问存储单元的时候,都是直接使用唯一直接访问。

1
2
3
4
gh503@gh503-OMEN-by-HP-Laptop:~$ lsblk -d -o NAME,TYPE,ROTA,VENDOR,TRAN,PHY-SEC,LOG-SEC,SIZE,PATH
NAME TYPE ROTA VENDOR TRAN PHY-SEC LOG-SEC SIZE PATH
sda disk 0 ATA sata 4096 512 119.2G /dev/sda
sdb disk 1 ATA sata 4096 512 931.5G /dev/sdb

上面为ATA生产的2块sata接口硬盘,sda为固态,sdb为机械硬盘。物理扇区大小均为4kB,逻辑扇区均为512B。

两块硬盘都是4k盘,最小存储单元都是4KB。但是操作系统仍然读写512B,硬盘增加了一个转换层来模拟512B操作,先读4K,再写对应的512B,最后以4K写入磁盘。

字 word

字的定义,表示自然的数据单位。在计算机中,表示一次性处理事务的固定长度位组。这个很好理解,计算机处理数据就像人类语言表达一样,我们也使用文字或单词(word)来表达。

字不是固定长度,由计算机CPU中数据总线宽度决定。如果数据总线宽度32bits,字长32bits;如果数据总线宽度64bits,则字长64bits。而字节长度在不同的计算机中,我们认为都是8bits。存储单元可以是字、字节,两者没有必然联系。可以根据实际情况进行换算。

1
2
3
4
5
6
gh503@gh503-OMEN-by-HP-Laptop:~$ uname -m
x86_64
gh503@gh503-OMEN-by-HP-Laptop:~$ getconf LONG_BIT
64
gh503@gh503-OMEN-by-HP-Laptop:~$ getconf WORD_BIT
32

操作系统位数 <= 数据总线宽度。如果要看操作系统多少位的,使用uname -m,返回x86_64则为64位,如果是i386/i686则位32位;对于arm,显示armv7l为32位,显示aarch64为64位。

数据总线宽度 = CPU中寄存器位数 = CPU位数

LONG_BIT也表示查看操作系统位数。
WORD_BIT查看机器字长,这里是32位,4个字节。也即整数和指针数据的标称大小

数据读写

数据的高低字节

1个字节=8bits,高低2个字节=16bits,用16进制形式表达为0xABCD
我们知道16进制1位需要4bits来表达0~15。也就是2位16进制需要8bits,1个字节。

这里AB为高字节,CD字节(10进制1234中,12高位,34低位)。

地址的高低

我们已经按存储单元给存储空间进行编号,每个存储单元都有自己的地址。从0到2^N-1,这里N为地址总线的宽度。
如果将地址换算成16进制的话,就是0x00x3FFFFFFFFFFFF(N=32)

低地址:从0开始,前面的地址
高地址:从0开始,后面的地址,最后的地址最高。两者相对的。

存储单元如果从前往后使用,称之为往高地址方向生长。反之,称之为往低地址方向生长。

存数据

当我们拿到数据时,该怎么存呢?
是优先用高地址还是地地址?
如果一份数据需要用到2个或者多个存储单元时,应该把高字节放到高地址还是低地址?

确实有不同的方案。

  • 数据: 0xABCD
  • 存储单元:0x1234

第一种方法:我们将数据从左往右存入存储单元中,有点类似字符串顺序处理。称之为“大端模式(Big-endian)”。即:
0xAB -> 0x12
0xCD -> 0x34

第二种方法:将小的数据放入低地址,将大的数据放入高地址,这种处理方法和我们的逻辑一致。称之为“小端模式(Little-endian)”。即:
0xAB -> 0x34
0xCD -> 0x12

取数据

当我们取数据的时候,读出来的字节应该怎么恢复为原始数据?

  • 存储单元:0x1234
  • 存储数据:0xABCD

如果是大端模式:由于是按字符串方式存的,所以取的时候也一样,直接还原为0xABCD
如果是小端模式:由于是按大小高低逻辑方式存的,所以低字节的数据在低位,还原为0xCDAB。不是0xDCBA(半字节)或0xABCD(双字节),因为这里例子存储单元是按字节操作的。

那计算机到底是哪种模式,可以使用程序测试:
1.创建占用2个存储单元的数据并赋值,当然两个存储单元的数值肯定要不同,然后逐个读取
2.如果低位是高字节,是大端;如果低位是低字节,是小端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
gh503@gh503-OMEN-by-HP-Laptop:~$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Address sizes: 39 bits physical, 48 bits virtual
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Vendor ID: GenuineIntel
Model name: Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz
CPU family: 6
Model: 158
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1

这里从lscpu命令返回可以看到Byte Order显示为Little Endian,即为小端模式。这里物理内存地址宽度39bits,寻址空间2^39个单元,即512GB。虚拟内存地址宽度48bits,寻址空间2^48个单元,即256TB。

参考文章

[1] wiki-字节定义
[2] 为什么计算机的一个存储单元是八位?

计算机主存和外存设备的工作原理

https://gh503.github.io/2024/04/28/3b23abe3a30b/

Author

gh503

Posted on

2024-04-28

Updated on

2024-07-17

Licensed under