其他分享
首页 > 其他分享> > UBI子系统学习

UBI子系统学习

作者:互联网

UBI子系统

UBI子系统简介

UBI子系统是运行在mtd子系统之上的一个flash管理系统,对上层屏蔽了flash的一些特性(例如坏块管理、磨损平衡等),并且提供了UBI卷(类似于分区)的概念;
UBI子系统只适用于传统的Flash(nor/nand),不适用于消费类Flash(mmc、emmc等),原因是它们都有自己的一套坏块管理和磨损平衡的机制。

相关概念

PEB和LEB

PEB(Physical Erase Block)物理擦除块是真实物理设备中的块,因为Nand Flash的擦除最小单位是块,因此叫做擦除块;以GD的flash为例 1块的大小是128K,1页大小是2048Byte+128Byte。
LEB(Logical Erase Block)逻辑擦除块是映射到物理擦除块上的,由于UBI会在每个PEB前面添加自己的UBI头,因此实际大小会比PEB要小。

UBI卷

UBI卷是一组连续的逻辑擦除块(LEB),每个LEB会动态映射到PEB上,由UBI子系统本身管理,这个管理对用户是隐藏的,当某个PEB损坏的时候,对应LEB会自动取消对这个PEB的映射,然后映射到另一个好的PEB上,这个过程用户是没有感觉的,因为它操作的还是那个LEB,并不知道底层擦写的物理块已经变了。
UBI卷有两种类型:动态卷和静态卷。静态卷是只读的卷,里面的内容由CRC-23校验码保护,并且静态卷的大小是已知的;动态卷是可以读写的,数据的完整性由文件系统保证,并且动态卷的大小不是固定的,可以重新指定大小。

磨损平衡

由于Nand Flash本身的特性,擦除次数是有限制的,通常在一个分区里面(例如userdata分区)并不会一直都是填满数据的,大部分的时间大部分空间都是空的,如果按顺序对Flash进行擦写,那么擦写的块就会集中在分区前面的block,这样造成的后果就是大大增加了前面的block的损坏概率,而后面的block又完全没用到。
UBI提供了一个磨损平衡的机制来保证分区里面的每个block的擦除次数的最大差值不会超过一定值,这样就能保证每个block都有机会被使用到;这时候逻辑块的作用就体现出来了,上层操作的还是连续的逻辑块,但是ubi将LEB映射到了不同的PEB,这样底层擦写的就是另一个物理块,实现了磨损平衡,而且上层不需要做任何其他的操作。

坏块管理

Nand Flash生产过程中或使用过程中都有可能产生坏块,这是由Flash本身的特性决定的,一个Nand Flash出厂的时候只能保证第0个block一定是好的,其它的每个块都有可能是坏块,但出厂时总的坏块数不会超过2%,在后面的使用过程中也可能会随机产生坏块。
UBI本身就是一个坏块管理的中间件,提供坏块管理的功能:
UBI在创建的时候是会预留一个坏块池,运行过程中发现一个物理擦除块变成坏块时,它就会从坏块池中拿出一个好的块替换掉这个坏的块,并将数据从这个块中迁移到好块里面。
在这里插入图片描述
更多的时候LEB和PEB的映射关系不会像上图那样有序,而是杂乱无章的,因为有磨损平衡的存在,当同步数据的时候,ubi就可能会对逻辑块进行re-map操作。

位翻转(bit-flips)

Nand Flash在使用过程中容易发生位翻转,发生位翻转可以由ECC校验并矫正,但ECC的纠错能力是有限的,一般512字节8位的ecc校验码,能纠正1bit位翻转,能发现2bit位翻转,更多的就不能保证发现,并且超过1位就不能纠正了。
UBI会检查每个block是否发生了位翻转,并且将数据转移到其他PEB来解决问题,这个过程称为scrubbing(擦洗)

UBI 头(headers)

UBI在每个非坏PEB开始需要存放2个64Byte的头,分别是EC头(Erase Counter Header)VID头(Volume Identifier Header)

位置

EC头始终位于PEB偏移量为0处并占用64个字节,VID头则位于下一个最小IO单元开始的地方,也占用64个字节,例如:

擦写时机

EC头和VID头位于不同IO单元是因为,EC头和VID头写入的时机并不一样。
当UBI关联到一个MTD设备的时候,会去扫描整个MTD设备,并在RAM中建立映射关系,保存在ubi_attach_info数据结构中;第一次关联MTD设备时,还需要先将MTD设备格式化成UBI格式,也就是在每个物理擦除块前写入EC头。
UBI擦除PEB后,它就会增加擦除计数器的值,并将EC头重新写入。
当UBI将LEB和PEB映射的时候,才会将VID头写入PEB中;VID头被写入的时候,更像是这样子:

  1. 当进行LEB映射或者操作一个没有映射的LEB的时候,ubi会去寻找一个合适的**空闲(free)**的PEB,然后将VID头写入(此时EC头是必须已经存在的,并且不会更改EC头);
  2. 当发生数据迁移的时候,LEB会取消映射PEB,并将这个PEB放进擦除(erase)链表中,PEB执行擦除完成后会立马写入EC头,并且EC头的擦除计数器+1,此时不会写入VID头;LEB会执行1操作,重新映射另一个PEB。

ps:
1.PEB擦除到重新写入EC头中间如果发生重启,EC头将会丢失,重启后ubi会扫描mtd设备,重新写入一个拥有平均计数器的EC头;
2.PEB的擦除和写入是异步的,也就是说可能会发生层新的LEB已经映射了新的PEB并写入了VID头,但是旧的PEB还没有被擦除,此时发生重启,就会有两个PEB被同一个LEB所映射(VID头拥有相同的卷ID和逻辑块号);此时就会选择 sqnum(全局LEB序列号) 更大的PEB

层卷(Layout Volume)

ubi层卷是必须存在的一个卷,并且这个卷对用户隐藏,使用的时候并不会发现有这个卷的存在;层卷需要占用两个块的内存空间,层卷里面保存了每个卷的信息,并且保存了两份,一个block一份,防止丢失。也就是说UBI子系统中能创建的最大卷的数量和bolck的大小是有关的,但最多不超过128个卷。

UBI子系统的主要功能

UBI管理开销

UBI子系统提供了这么多功能,付出的代价就是需要消耗额外的内存空间来存放这些管理信息。UBI管理产生的开销主要有以下:

  1. 层卷,需要2个block;
  2. 磨损平衡,需要消耗1个block;
  3. 原子更改逻辑块,需要消耗1个block;
  4. 坏块管理预留坏块池,需要预留20个block;
  5. UBI标头,每个block前都要预留空间存放2个header,所占用空间和实际UBI分区大小有关;
    对Nand Flash(128M,block=128k,page=2k)来说,37M大小的UBI分区的管理开销应该为:ALL = 24 x 128k + (296 - 24) x 2 x 2k = 4160k ≈ 33 block

标签:LEB,子系统,学习,擦除,block,坏块,UBI,PEB
来源: https://blog.csdn.net/FOUREYESPIG/article/details/118944730