千家信息网

针对Flash的Linux UBI子系统是怎样的

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章给大家介绍针对Flash的Linux UBI子系统是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。正文UBI简介UBI全称是Unsorted Block Image
千家信息网最后更新 2026年11月02日针对Flash的Linux UBI子系统是怎样的

这篇文章给大家介绍针对Flash的Linux UBI子系统是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

正文

UBI简介

UBI全称是Unsorted Block Images,上图为UBI在系统中的层次结构,最下面是flash层(包括flash控制器,各个flash驱动代码,spi-mem层等);MTD层是对flash层的抽象,一个flash可能被划分成不同的分区,每一个分区都会对应一个MTD设备;UBI层是基于MTD层之上的更高层,UBI层抽象出一个个逻辑擦写块,每个逻辑擦写块都有一个物理擦写块与之前对应,有了这个映射,我们就可以加一些软件算法,达到擦写均衡的目的,从而提高flash的使用寿命;再往上是基于UBI层实现和各种文件系统,比如UBIFS。

flash存储的内容

首先介绍几个概念:

  • PEB:physical eraseblocks 也就是对应flash上的一个擦写块

  • LEB:logical eraseblocks 软件上的概念

  • Volume:卷

如上图为flash中(或者说flash一个分区中)数据组织结构:

  • ubi层对flash的管理是以擦写块为单位的,LEB对应软件上的概念,PEB对应flash上一个实实在在的擦写块,每一个LEB对应一个PEB。

  • 往上看多个LEB可以组成一个volume,也就是说,可以根据不同的功能,将LEB划分到不同的卷中;其中valume-layout是一个ubi内部使用的卷,用来存放该MTD设备上所划分的各个卷的信息,其包含两个LEB,它们存储的内容是一样,互为备份。

  • 往下看每个PEB的内容包含3部分ech(erase counter header),vidh(volume identifier header),data。下面会介绍具体含义。

代码实现

linux对UBI层的代码实现大致可以总结为3个方面:

首先数据是存储在flash中的,因此需要将flash中的相关信息读到内存中,同时也可以检查出flash中的坏块

数据读到内存后,需要按照内部的逻辑关系组织起来(比如将正在使用的PEB放到红黑树上管理起来,空闲的PEB也放到红黑树上管理起来)

在内存中有了这些数据的关系后,就可以对其进行操作(比如读写操作,volume增加,删除,扩容等操作,擦写均衡操作)

将flash数据读到内存

UBI初始化时代码调用流程如上图,最终会调用scan_all() 函数, scan_all() 函数会遍历该MTD设备

中的每一个PEB,从中读出ech和vidh,它们的定义如下。

ech的定义如上,其中:

  • ec:表示该PEB被擦写的次数,借助该字段我们就能够找出被擦写次数最少的PEB,从而达到擦写均衡的目的

  • vid_hdr_offset:表示vidh在该PEB中的偏移位置

  • data_offset:表示实际数据在该PEB中的偏移位置

  • vidh的定义如上,其中:

  • vol_id:表示该PEB属于那一个volume

lmun:表示LEB在volume中的编号,该字段与PEB在MTD设备中的编号形成映射关系通过对MTD设备的每个PEB进行遍历,可以得知各个PEB的情况,或是被使用的,或是空闲状态,或者已经损坏,这些信息会被临时记录在struct ubi_attach_info 结构中,遍历过程中的具体细节,可以参考scan_all() 函数。

组织数据结构

遍历PEB后,会将flash信息保存在临时的结构struct ubi_attach_info 中,接下来会将struct ubi_attach_info 中的临时信息保存到全局结构struct ubi_device *ubi_devices 中,代码如下:

分为三个步骤,分别是对volume的初始化,对wear-leveling子系统的初始化,对eba(Eraseblock Association)子系统的初始化;下面我们分别看下。

volume & EBA子系统初始化

前面有介绍到volume-layout是UBI内部使用的一个卷,其包含两个LEB(互为备份),对应PEB中的数据内容如上图,data(灰色)部分是一个struct ubi_vtbl_record 结构数组,记录了当前UBI设备所有卷的信息, ubi_read_volume_table() 函数先遍历临时结构struct ubi_attach_info 找出volumelayout所在PEB,然后 读出struct ubi_vtbl_record 结构数组并保存到内存中,也就是struct ubi_device 的struct ubi_volume *volumes[] 字段中,初始化后的数组结构如下图,其中struct ubi_volume *volumes[] 是一个指针数组,数组中的每一个元素都是struct ubi_volume 结构(详细过程见ubi_read_volume_table() 函数)。

在struct ubi_volume 结构体中,有一个比较重要的字段struct ubi_eba_table *eba_tbl ,该字段记录了当前volume中所有LEB与PEB的映射关系,其中struct ubi_eba_entry *entries 是一个数组结构,每一个元素对应一个struct ubi_eba_table 结构体, struct ubi_eba_entry *entries 数

组的下标对应于LEB的编号,数组元素的内容对应EB的编号,这样就将LEB与PEB关联起来了(详细过程见ubi_eba_init() 函数)。

wear-leveling子系统初始化

在UBI中将PEB分为4种情况,正在使用、空闲状态、需要擦除、已经损坏,各个状态的PEB被放到不同的红黑树中管理。在ubi_eba_init() 函数中,会先分配一个struct ubi_wl_entry 指针数组并存储在sruct ubi_wl_entry **lookuptbl 字段中,数组下标为PEB的编号,数组内容记录了PEB的擦写次

数与编号信息,每一个PEB都有一个这样的结构与之对应如下图。

另外各个PEB还根据状态放到不同的红黑树管理起来,上图画出了used, free, scrub三种状态的红黑树,其中红黑树是以擦写次数为顺序排列的,最小的擦写次数排列在最左边,如果擦写次数相同,则比较PEB的编号,编号小的排在树的左边,而对应的值为struct ubi_wl_entry 指针数组中的一个元素。

调用ubi_eba_init() 函数后,wear-leveling子系统也就初始化完毕,在内存中会形成上图中的数组关系。

UBI层操作

经过前面的初始化,各个数据的结构关系已经保存在内存中了,因此UBI层的操作其实就是对内存中这些数据的操作。

从用户空间角度看,UBI初始化后会对应三类字符设备,分别为/dev/ubi_ctrl 、/dev/ubix (x = 0, 1, 2...), /dev/ubix_y (x = 0, 1, 2..., y = 0, 1, 2),它们对应的操作函数如下代码。

  • ubi_vol_cdev_operations:是针对某个volume(/dev/ubi1_0等)来操作的,从volume的角度只能看到其中包含的PEB,因此它的操作也是围绕PEB进行的。

  • ubi_cdev_operations:是针对UBI设备(/deb/ubi0等)进行操作的,从UBI设备的角度可以看到不同的volume,因此可以对volume进行创建,删除,扩容等操作。

  • ubi_ctrl_cdev_operations:是针对UBI层(/dev/ubi_ctrl)的操作,从该角度可以看到UBI设备,因此可以对UBI设备进行创建,删除操作。

举个例子

需求:假如我们想要对/dev/ubi1_0 这个volume进行扩容,我们应用怎样操作?

用户空间将volume_id,size两个参数传递到内核空间

在内核空间我们根据volume_id在struct ubi_volume *volumes[] 数组中找到volume的handler

因为需要扩容(要分配更多的LEB),所以要重新分配struct ubi_eba_table *eba_tbl 数组,并将旧数组中的数据拷贝到新数组中

对于新增的LEB,我们需要从free树上申请,建立LEB到PEB的映射关系并保存到struct ubi_eba_table *eba_tbl 数组,另外还需要更新PEB中ech和vidh,表明该PEB属于那个volume

上面这一系列操作是我自己的想法,并非kernel实现代码(具体实现可以参数ubi_cdev_ioctl() 函数)。这里想表达的意思是,在UBI初始化完成后,在内存中已经存在了各个volume,各个LEB/PEB之间的关系,因此对于UBI的操作,理论上我们是都可以完成的,所差的只是代码实现;程序=算法+数组结构,这里的数组结构已经有了,而算法就是UBI层的各种操作,这里的代码其实每个人都可以实现的,只不过有好有坏,所幸kernel已经帮我们实现了,我们可以参考学习。其实别人写的文章只能提供个大概,真正的细节只有在源码中才能获得。

擦写均衡

flash的擦写块都是有寿命限制的,如果频繁的擦写flash的某一个PEB,很快这个PEB就会损坏,而擦写均衡的目的就是将擦除操作平均分配到整个flash,这样就能提高flash的使用寿命。那怎样将擦除操作平均分配到整个flash呢,要达到这个条件还是有些难度的,因此我们退一步,将条件修改为PEB的最大擦写次数与最小次数的的差值小于某个值。

比如flash中包含20个PEB,其中数字表示该PEB被擦写的次数,我们约定擦写次数的差值最大为15,现在flash中PEB的最小与最大擦写次数分别为10、39,由于超过门限值,因此需要我们想一些方法,增加擦写次数为10的PEB被擦写的机会,减少擦写次数为39的PEB被擦写的机会,从而使整个flash的擦写次数趋于平均。具体的实现后面会介绍。

擦写时机

linux kernel会在下面两个位置调用擦写均衡:

  • wear-leveling子系统初始化完成时会检查一次是否需要擦写均衡,此时是一个初始状态,是检查的一个时机。

  • 当要擦除某个PEB的时候,此时擦写次数会增加,有可能达到擦写均衡的要求,此时也是一个检查的时机。

擦写条件

除了上面的调用时机,擦写均衡还有一些其它的条件限制,如下图为擦写均衡的流程图:

  • 当scrub红黑树上有节点时,一定需要进行擦写均衡。在遍历flash的每个PEB时,如果发现在从flash中读出的数据有位翻转的情况,就会加上scrub标志,并放到scrub红黑树上维护起来,表示该PEB需要被擦写;在擦写均衡时,先取出scrub树最左边节点e1,再从free树中找一个合适的节点e2,然后读取e1对应PEB的数据,如果读取的数据还有问题,就会结束本次擦写;如果没有问题就会把e1数据copy到e2位置,并擦除e1数据完成本次擦写均衡操作。

  • 当scrub树上没有节点时,会从used树上取出最左边节点e1,并从free树上找一个合适的节点e2,然后检查e2与e1的PEB擦写次数的差值是否大于门限值,如果大于,则将e1数据copy到e2位置并擦除e1数据完成本次擦写。为什么这样做,原因是used树中的节点已经被初始化过(先整个擦除,然后写入ech和vidh,后面再写入数据也不需要擦写)所以不会有擦除操作,在free树上的节点,在被使用前需要擦除一次,所以把擦写次数大的PEB放到used树上减少被擦写的机会,把擦写次数小的节点放到free树上增加被擦写的机会,这样就达到了擦写均衡的目的。

  • 另外在free树上选择一个合适的节点,什么是适合和节点?最简单的方法就是从free树的最右边拿一上节点(擦写次数最大的节点),然后与used树上取下的最左边的节点比较,看看差值是否超过门限值。但实际情况可能会更复杂些,如下代码29行,是kernel中在free树上选择节点的方法,其限制了最大擦写次数为free树最左侧节点 + WL_FREE_MAX_DIFF,看上面的注释说在某些情况下会出现不断擦写某一个或几个PEB的情况,所以作了这样一个限制。(没有想道是什么情况??)

关于针对Flash的Linux UBI子系统是怎样的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

数组 次数 数据 结构 节点 均衡 设备 函数 代码 子系统 内存 内容 信息 情况 不同 字段 状态 最大 上图 位置 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 云南咖啡 互联网科技公司经营范围 互联网科技公司起名 互联网属科技 美国互联网科技巨头监管 金融科技与互联网金融 互联网 卓越科技 善班互联网科技有限公司 互联网公司会议桌创意科技软装饰 西藏七维空间互联网科技有限公司 阿里互联网科技公司 福建科技产业互联网发展 深圳市优智互联网科技有限公司 米聚互联网科技南京有限公司排面 互联网科技和法律行业 互联网数据科技专业 互联网科技资金流入 山东大美朱楼互联网科技有限公司 陕西九四连强互联网科技有限公司 利用互联网等科技手段 广州紫鲸互联网科技有限公司 科技赋能下的互联网金融 互联网科技卖菜 滨湖区互联网智能科技产品供应 互联网科技公司的市场部门 深圳市运趣互联网科技有限公司 花神(南京)互联网科技有限公司 互联网科技大奖都有哪些公司 美国互联网科技实力 上海旺乐尼互联网科技有限公司
0