3、地址映射基础:逻辑地址与物理地址、地址映射的概念、地址映射的层次结构

好,咱们今天聊聊地址映射。这玩意儿说白了,就是存储系统里最核心的「翻译官」。

你想想看,应用程序员写代码的时候,哪管你硬盘里哪个扇区、哪个块?人家眼里只有「文件A的第100个字节」。但硬件不认这个啊,它只认「柱面、磁头、扇区」或者「LBA逻辑块号」。这两者之间怎么对上号?嗯,这就是地址映射要干的事。

3.1 逻辑地址 vs 物理地址

先搞清楚两个基本概念。

逻辑地址,也叫虚拟地址。是上层软件看到的地址空间。比如你写fseek(fp, 1024, SEEK_SET),这个1024就是逻辑地址。它连续、从0开始、好理解。

物理地址,是硬件真正访问的地址。比如磁盘的LBA 0x12345678,或者NAND Flash的Block 100 + Page 5。它不连续、有坏块、有保留区。

我当年做第一个SSD FTL(闪存转换层)的时候,就栽在这个坑里。上层以为地址是连续的,底层NAND却动不动冒出个坏块。逻辑地址0x1000映射到物理地址0x2000,但0x2000坏了怎么办?得赶紧重映射到0x3000。这就是地址映射要解决的第一个问题——屏蔽底层缺陷。

核心区别一句话:

  • 逻辑地址:连续、稳定、上层可见
  • 物理地址:离散、动态、底层管理

3.2 地址映射的概念

地址映射,就是把逻辑地址翻译成物理地址的过程。听起来简单?其实门道很深。

我习惯用一个比喻:地址映射就像一本「电话簿」。你查「张三」这个名字(逻辑地址),电话簿告诉你号码是138xxxx(物理地址)。如果张三换号了,你只需要更新电话簿,不用改名字。

在存储系统里,这个「电话簿」就是映射表。常见的映射粒度有:

映射粒度 典型场景 优点 缺点
扇区级(512B/4KB) 传统HDD、早期SSD 灵活,无写放大 映射表巨大
块级(256KB~4MB) 企业级SSD、NAND Flash 映射表小 有写放大
混合映射 现代消费级SSD 兼顾灵活与开销 实现复杂

这里要注意:映射粒度越细,灵活性越高,但映射表占用的内存也越大。我见过一个项目,为了追求极致性能,用了4KB粒度映射,结果1TB的SSD需要256MB的DRAM来存映射表。成本直接炸了。

我的经验: 对于消费级产品,建议用混合映射。热数据用细粒度,冷数据用粗粒度。既保证性能,又控制成本。

3.3 地址映射的层次结构

地址映射不是一层搞定的。现代存储系统通常有三级映射:

第一层:文件系统层 逻辑地址(文件偏移 + 文件ID) → 逻辑块号(LBA) 示例:ext4的inode映射、NTFS的MFT 第二层:FTL/设备层 逻辑块号(LBA) → 物理块号(PBA) 核心:映射表查找、坏块管理、垃圾回收 第三层:硬件层 物理块号(PBA) → 芯片/通道/片选/页偏移 示例:NAND的CE#、R/B#、ALE/CLE控制 图:地址映射的三层结构

为什么要分这么多层?

第一层:文件系统层。这一层负责把「文件名+偏移」翻译成「逻辑块号」。比如你打开一个文件,读第100个字节,ext4会查inode表,找到这个文件对应的数据块在LBA 0x5000~0x500F。这一层我建议用B+树来管理,查找效率高,适合大文件。

第二层:FTL/设备层。这是存储设备内部的事。它把LBA翻译成PBA。为什么需要这层?因为NAND Flash有坏块、需要磨损均衡、需要垃圾回收。这些脏活累活,FTL全包了。我曾经调试过一个SSD,发现写入性能忽高忽低,查了半天,原来是FTL在做垃圾回收时把映射表锁住了。后来改成分段映射+写时复制才解决。

第三层:硬件层。这一层最底层。PBA到了这里,要拆解成具体的芯片、通道、片选信号。比如PBA 0x12345678,可能对应Channel 0、CE# 1、Block 100、Page 5。这一层的映射通常是固定算法,比如取模运算,不需要查表。

注意: 三层映射不是绝对的。有些嵌入式系统为了省资源,会把文件系统和FTL合并。但代价是灵活性下降,换文件系统就得重写FTL。我个人不建议这么做,除非你确定这辈子不换方案。

3.4 映射表的实现方式

映射表怎么存?这是个大学问。我见过三种主流方案:

  1. 全映射表:所有逻辑地址到物理地址的映射都存下来。简单粗暴,但内存占用大。1TB SSD用4KB粒度,需要2亿条记录,每条4字节,就是800MB。DRAM都装不下。
  2. 页级映射:只缓存热数据的映射,冷数据从NAND里读。这是目前的主流方案。比如三星的V-NAND就用这个。
  3. 混合映射:热数据用页级,冷数据用块级。我参与的一个项目就是这种方案,性能比纯页级提升了15%,内存占用还少了30%。

避坑指南: 我曾经在项目里用了全映射表,结果掉电后重建映射表花了整整5分钟。用户直接投诉。后来改成定期刷写映射表快照+增量日志,掉电恢复时间降到2秒以内。

3.5 地址映射的校验机制

映射表不能出错。一旦错了,数据就读不回来了。所以要有校验。

常见的校验手段:

  • CRC校验:每条映射记录加4字节CRC。读的时候校验,不对就报错。
  • 双备份:映射表存两份,一份在主区,一份在备份区。主区坏了读备份。
  • 日志型映射:不直接修改映射表,而是追加写日志。掉电后重放日志恢复。这是最安全的方式,但写性能会受影响。

我个人习惯用CRC + 双备份。日志型太慢,不适合高性能场景。双备份虽然多占一倍空间,但NAND便宜啊,安全第一。

小技巧: 双备份不要放在同一个芯片上。万一那个芯片坏了,两份都完蛋。要跨芯片、跨通道备份。

好了,地址映射的基础就这些。记住一句话:映射表是存储系统的命根子。它坏了,数据就丢了。所以设计时,宁可多花点成本,也要保证映射表的可靠性和恢复能力。


可可精品资料库