UBIFS文件系统(一)

UBIFS文件系统(一)

本文主要介绍ubifs的基本概念,后续会描述ubifs各个关键过程的实现细节。

磁盘结构

ubifs文件系统将整个磁盘空间划分为superblock、master、log、lpt、orphan和main六个区域,其区域划分如下所图所示:
在这里插入图片描述

其中,superblock区域固定占用LEB0,master区域固定占用LEB1和LEB2,其他区域占据的LEB数量则视该文件系统分区实际占有的总的LEB数量而定,orphan区域一般占用1到2个LEB。

superblock区域保存文件系统的固定参数,参数在格式化时写入,除了leb_cnt元素和UBIFS_FLG_SPACE_FIXUP标志位会在首次挂载时被改变,其他元素皆为只读。

master区域中的两个LEB相互备份,以确保在异常掉电的情况能够恢复master区域的内容。master区域的数据在每次发生commit的时候进行更新。

log区域记录日志数据的存储位置lnum:offs。ubifs是一种日志文件系统,文件数据采用异地更新的方式(out_of_place_update),即文件数据的更新不会每次都同步到flash,而是记录到日志区,当日志区的数据累计到一定程度时,才将数据同步到flash中。

lpt区域记录了磁盘空间中各个LEB的状态(free、dirty、flag),用于实现对LEB的分配、回收和状态查询。

main区域则保存文件的数据和索引。

文件索引

ubifs文件系统中的数据统一以node的形式顺序存储于LEB中,其中node包含metadata和data两部分:metadata标识了node包含的数据类型,包括ubifs_ino_node、ubifs_data_node、ubifs_dent_node、ubifs_xent_node和ubifs_trun_node五种;data部分则为实际的有效数据。node的长度根据数据类型的不同而有所差别,node在磁盘中的存储序列如下所示:

node的存储结构
ubifs采用一棵B+树对文件的数据进行索引:其中保存文件路径信息的node组成B+树的索引节点,组成文件数据的node组成B+树的叶子节点。B+树中的索引节点在内存中为ubifs_znode,该结构体只有部分数据需要保存到flash中,而其他部分只存在于内存当中,保存到flash中的部分组成结构体为ubifs_idx_node。ubifs将用于索引文件数据的B+树称之为TNC(Tree Node Cache)树,其索引结构如下所:
TNC树
假设B+树的数高为N,每个索引节点包含的最大分支数为M,则该B+数能够索引到的最大叶子节点数为M的(N+1)次方个。在ubifs的TNC中,B+树的树高N默认为bottom_up_buf=64(该值可以根据实际情况进行扩展);每个索引节点包含的最大分支数M为8(该值在进行文件系统分区格式化时指定),而每个索引节点实际占有的分支数记录与索引节点的child_cnt域中。

TNC中Level 1至Level N的内部索引节点(ubifs_znode)的分支(ubifs_zbranch)分别指向下一级索引节点的存储位置(lnum:offs:len),而Level 0处的索引节点的分支则指向数据节点的存储位置(lnum:offs:len)。保存索引节点和数据节点的存储位置,而不保存节点的实际数据内容,可以有利用在同一个LEB中保存多的节点,减少LEB的访问次数,提高访问效率。B+树通过键值进行索引,数据节点的键值计算规则如下:
数据节点的键值计算
其中,对于同属于一个文件node的多个数据节点ubifs_data_node,其键值key按照block number进行区分;对于同属于一个文件node的多个目录项节点ubifs_dent_node,其键值key以目录项文件名的hash值进行区分;同理,ubifs_xent_node以attr entry的hash值进行区分。注意:在进行键值比较时,首先比较键值的低32位,再比较两者的高32位,因此同属于同一个inode的所有数据node都保存在B+树的相邻位置,这样便可以快速的找到同一个inode的各个数据node。在进行crash分析时,可能需要用到利用键值查找znode/zbranch的过程。此外,TNC的叶子节在内存中集合被称之为LNC(Leaf Node Cache),便于查找需要频繁访问的目录项ubifs_dent_node以及扩展属性项(噶和目录项共用一个数据结构)。

索引节点(index-node)和叶子节点(非索引节点 non-index-node)永远保存在不同的LEB中,即同一个LEB不可能同时包含index node和non-index node。

空间管理

ubifs采用另一个B+树对磁盘的空间进行管理,此时B+树的叶子节点保存的是LEB属性(空闲空间free、脏空间dirty和是否是索引LEB),该B+树在ubifs中被称之为LPT(LEB Props Tree),其索引结构如下图所示:
LPT
LPT和TNC两者的区别在于:TNC中叶子节点和索引节点采用统一的数据结构ubifs_znode表示,其保存的内容一致均为key、lunm、offs和len,而在LPT中其索引节点对应的数据结构为ubifs_nnode,保存索引节点所在的lnum和offs,其叶子节点对应的数据结构为ubifs_pnode,保存LEB的空间属性free、dirty和flag;TNC各索引节点的分支数不确定,但在LPT中每个索引节点包含固定的分支数fanout=4;对于固定大小的文件系统分区,TNC的树高不确定,其树高由文件系统实际包含的文件数(数据节点的数量)决定,而LPT的树高固定为log4M,M为main区域的LEB数量。TNC中需要根据不同的数据节点计算键值,并作为节点的一个元素伴随节点一起插入到B+树中,而LPT中不需要额外的键值用于索引节点,而是直接以LEB号作为键值对节点进行索引,LPT叶子节点从左到右其LEB号依次为LEB(main first) ~ LEB(main first + M)。

LPT存在big model和small model两种存储模式,当所有的nnode、pnode、ltab、lsave能够存储到一个LEB中时,使用small model,否则使用big model。两种模式的区别在于回写磁盘时的规则不同,对于small model其在flash中的数据存储格式如下所示:small mode的LPT存储格式
LPT为main区域LEB的空间管理索引树,而ltab则为LPT区域的空间管理索引树,标记LPT区域的LEB的使用情况。

日志管理

ubifs是一种应用于nand flash之上的文件系统,对nand flash进行写操作之前必须以earse block为单位对其进行擦除,并且擦除之后只能对其写一次。在这种情况下,对文件数据先读、再擦、再写的inplace_update方式就变得非常耗时,因此ubifs采用out_of_place_update(即异地更新)的方式对文件数据进行操作。异地更新是指将修改的文件数据写到已经擦除过的磁盘块,并且在内存中修改文件索引将其指向新的数据块,此时原始的文件索引关系仍保存在磁盘,而新的文件索引存储在内存当中,存储在内存中的索引关系会根据情况定时的同步到磁盘中(在ubifs中称之为commit),此时才完成真正的文件数据修改。

ubifs将所有写入新数据的磁盘块称之为日志区(journal),它并不是一段连续的LEB块区域,而是由任意位置和任意多个main区域的LEB组成。根据不同的数据类型,ubifs包含三个动态变化的日志区,分别是GC、BASE和DATA。ubifs以LEB为单位对flash进行写操作,因此每一个日志区在内存中都维护一个称之为journal head的缓冲区,其大小与LEB相同,当ubifs写数据时总是先将数据写到对应的缓冲区中,当缓冲区填满之后才将数据实际写到磁盘当中,这也是为了减少对磁盘的操作次数。

ubifs将每个作为日志区的LEB的信息(lnum:offs)以ubifs_ref_node的数据结构记录于log区域,为区分log区域中的数据是否同步到了flash,ubifs在每次同步操作时向log区域写入一个ubifs_cs_node以作标识。ubifs中的所有node结构体都包含一个统一的头部元素为ubifs_ch,在元素中包含有一个标记该node创建时间的squem,因此log区域中大于ubifs_cs_node的squem的ubifs_ref_node即为尚未被同步到flash的日志LEB,反之则为已经被同步到flash的日志LEB,其对应的ubifs_ref_node则可以被删除以腾空间。当系统发生异常掉电时,ubifs扫描log区域的LEB,便可对掉电前的TNC和LPT等数据结构进行重建,从而达到掉电恢复的目的。

在数据进行同步(即commit)时,ubifs_cs_node总是寻找一个新的LEB,并占据其起始位置,每当一个LEB加入到日志区时,ubifs便会创建一个ubifs_ref_node结构体,并将该结构体同步到磁盘中。log区的数据排列结构如下所示:
log区数据排列结构
ubifs_cs_node和ubifs_ref_node的数据结构分别如下所示:
ubifs_cs_node和ubifs_ref_node
ubifs在内存中还维护了一个与ubifs_ref_node对应的bud结构便于快速查找日志区的LEB。

  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要解开ubifs文件,你需要使用相应的工具和库来处理ubifs文件系统。Python本身没有直接支持ubifs文件的解析和操作的库,但你可以使用其他语言编写的库来实现。一个常用的工具是ubireader,它是一个用于解析和操作ubifs文件系统的开源工具。你可以使用ubireader库来读取和提取ubifs文件系统中的文件和目录。你可以在Python中使用subprocess模块来调用ubireader工具,并通过解析其输出来获取所需的文件内容。以下是一个示例代码,展示了如何使用ubireader来解析ubifs文件系统中的文件: ```python import subprocess def extract_ubifs_file(ubifs_file, target_file): # 调用ubireader工具来提取ubifs文件系统中的文件 command = f"ubireader_extract_files {ubifs_file} {target_file}" subprocess.run(command, shell=True) # 调用函数来解析ubifs文件系统中的文件 extract_ubifs_file("example.ubifs", "example.txt") ``` 请注意,你需要先安装ubireader工具,并将其添加到系统的环境变量中,以便在Python中调用。此外,你还需要根据你的具体需求来修改代码中的文件路径和目标文件名。 希望这可以帮助到你解开ubifs文件。如果你有任何其他问题,请随时提问。 #### 引用[.reference_title] - *1* *2* *3* [UBIFS文件系统](https://blog.csdn.net/renlonggg/article/details/103610509)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值