jffs2文件系统浅析----第一章 认识linux文件系统与flash之间的交互流程

第一章 认识linux文件系统与flash之间的交互流程

1、概述

    总所周知,对于linux系统来说,上层采用VFS对所有文件系统的操作进行抽象,屏蔽了底层不同文件系统之间的实现差异。本文主要针对常用的闪存文件系统jffs2,与各位一起探讨下它的实现原理。

2、关键数据结构

2.1 文件系统基本功能

文件系统基本功能主要分为如下两种:
一、是将flash内block数据映射到内存中,供高软读写;
二、是将文件系统数据写入到flash中实现持久化存储;

2.2 常见jffs2数据结构

2.2.1 flash数据实体内核描述符jffs2_raw_node_ref

    通常jffs2文件系统最小描述实体用struct jffs2_raw_node_ref进行描述.

struct jffs2_raw_node_ref {
	struct jffs2_raw_node_ref *next_in_info;
	struct jffs2_raw_node_ref *next_phy;
	uint32_t flash_offset;
	uint32_t totlen;
};

其中:
1、一个文件的多个jffs2_raw_node_ref信息存储在next_in_info中,组成一个循环链表。
2、链表头指向ffs2_inode_cache的nodes域;链表尾则指向ffs2_inode_cache。因此对于文件系统来说,可以从链表的任意一个节点,开始遍历,将文件的所有信息从flash中读出。
3、flash_offset则表示在flash中的地址偏移
4、一个flash的earse_block的数据描述实体则由next_phy进行描述。其首位指针分别指向jffs2_earseblock的first_node和last_node。

2.2.2 文件实体内核描述符jffs2_inode_cache

    该数据结构体用以描述文件与数据之间的映射关系。每个文件在内核中用jffs2_inode_cache进行描述。

struct jffs2_inode_cache {
	struct jffs2_full_dirent *scan_dents;
	struct jffs2_inode_cache *next;
	jffs2_raw_node_ref *nodes;
	uint32_t ino;
	int32_t nlink;
	int32_t state;
}

其中:
1、 ino为当前文件在文件系统中的唯一索引号,该索引会和inode节点信息中的ino关联起来;具体取值在jffs2_add_ino_cache函数中实现;
2、scan_dents存放jffs2_raw_dirent的上层结构链表临时地址,扫描完后置为NULL
3、nlink为硬链接个数,在文件系统挂在时会计算指向当前文件的目录项个数;
4、next则指向下个文件的描述信息
5、nodes内则是每个文件的实际离散数据实体

    从下图中我们可以明显看出jffs2_inode_cache与jffs2_raw_node_ref之间的关系
在这里插入图片描述

    从中可以看出所有的文件实体描述符都存在一个hash表inocache_list中。并通过唯一标识ino找到对应的jffs2_inode_cache,再依次遍历jffs2_raw_node_ref找到文件对应的所有数据信息。

2.2.3 jffs2_raw_node_ref如何指向jffs2_inode_cache

    从上图中我们可以看到任意一个数据实体,都可以找到它对应地文件信息,但是图中指向的确是NULL。不知道各位读者对这个是否存在疑惑。让我们来看三段代码

1、内核描述符初始化

int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri)
{
    ...
	//写文件初始化时,将指向nodes自己
	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
	...
}

2、内核描述符与数据实体关联

struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t ofs, uint32_t len, struct jffs2_inode_cache *ic)
{
	...
	jeb->last_node = ref;
	if (ic) {
		ref->next_in_ino = ic->nodes;
		ic->nodes = ref;
	} else {
		ref->next_in_ino = NULL;
	}
	...
}

3、通过数据实体描述符指向内核描述符

static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
{
	while(raw->next_in_ino) {
		raw = raw->next_in_ino;
	}
	/* NB. This can be a jffs2_xattr_datum or jffs2_xattr_ref and
	   not actually a jffs2_inode_cache. Check ->class */
	return ((struct jffs2_inode_cache *)raw);
}

通过上述代码,我们可以清晰的看出整个文件的构建方法。(当前参考源码来自linux6.8.0)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值