yaffs2源码学习3:文件创建与删除
一、基本概念
在研究文件系统前,先对文件系统中涉及的基本的概念进行定义。
- 域(field):是基本数据单元。一个域包含一个值。
- 记录(record):是一组相关的域的集合,它可以看做是应用程序的一个单元。
- 文件(file):是一组相似记录的集合,它被用户和应用程序看做是一个实体,并可以通过名字访问。
- 文件管理系统:是一组系统软件,为使用文件的用户和应用程序提供服务。在典型情况下,文件管理系统是用户或应用程序访问文件的唯一方式,它使得用户和程序员不需要为每个应用程序开发专用软件,并且给系统提供了控制最重要资源的方法。
在嵌入式系统中,通常使用flash作为外部存储设备,而yaffs2是针对闪存的文件系统做的比较好的,本篇文章首先学习文件的创建和索引,文件系统怎么通过文件名来找到一个文件,然后介绍文件的删除。
二、文件创建
2.1 create file or directory
创建file或directory均转调用yaffs_create_obj完成,详细代码如下:
static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type,
struct yaffs_obj *parent,
const YCHAR *name,
u32 mode,
u32 uid,
u32 gid,
struct yaffs_obj *equiv_obj,
const YCHAR *alias_str, u32 rdev)
{
struct yaffs_obj *in;
YCHAR *str = NULL;
struct yaffs_dev *dev = parent->my_dev;
/* Check if the entry exists.
* If it does then fail the call since we don't want a dup. */
if (yaffs_find_by_name(parent, name))
return NULL;
if (type == YAFFS_OBJECT_TYPE_SYMLINK) {
str = yaffs_clone_str(alias_str);
if (!str)
return NULL;
}
in = yaffs_new_obj(dev, -1, type);
/*此时object位于“lost+found”,无object header,如果object为file,则已关联空的tnode tree*/
if (!in) {
kfree(str);
return NULL;
}
in->hdr_chunk = 0;
in->valid = 1;
in->variant_type = type;
in->yst_mode = mode;
yaffs_attribs_init(in, gid, uid, rdev);
in->n_data_chunks = 0; /*如果为文件,初始化记录文件的内容为chunk数*/
yaffs_set_obj_name(in, name);
in->dirty = 1;
yaffs_add_obj_to_dir(parent, in); /*放入期待的目录中*/
in->my_dev = parent->my_dev;
switch (type) {
/*根据不同的类型,对in进行相应的处理*/
case YAFFS_OBJECT_TYPE_SYMLINK:
in->variant.symlink_variant.alias = str;
break;
case YAFFS_OBJECT_TYPE_HARDLINK:
in->variant.hardlink_variant.equiv_obj = equiv_obj;
in->variant.hardlink_variant.equiv_id = equiv_obj->obj_id;
list_add(&in->hard_links, &equiv_obj->hard_links);
break;
case YAFFS_OBJECT_TYPE_FILE:
case YAFFS_OBJECT_TYPE_DIRECTORY:
case YAFFS_OBJECT_TYPE_SPECIAL:
case YAFFS_OBJECT_TYPE_UNKNOWN:
/* do nothing */
break;
}
if (yaffs_update_oh(in, name, 0, 0, 0, NULL) < 0) {
/*关联上object header*/
/* Could not create the object header, fail */
yaffs_del_obj(in);
in = NULL;
}
if (in)
yaffs_update_parent(parent);
return in;
}
从函数体中,我们看出调用了函数yaffs_find_by_name(parent, name),其中定义了文件名的字符数不能超过128个,又通过函数yaffs_get_obj_name()到函数yaffs_fix_null_name()来创建根据用户设置的文件名定义的文件。
in = yaffs_new_obj(dev, -1, type);创建该文件对象在tnode树的结构,
yaffs_add_obj_to_dir(parent, in);将in文件装入其父目录中。
yaffs_update_oh(in, name, 0, 0, 0, NULL),将in关联到其对象头上,更新其chunk_id。
2.2 link file
一个可被访问的file一定存在于某个绝对路径中,如/nand0/dev/yaffs2/readme.txt,文件readme.txt在绝对路径/nand0/dev/yaffs2/中,yaff2是它所在的目录,此时称readme.txt已经link。在删除readme.txt之前,必须将它unlink,即从绝对路径中剥离开来。
在link阶段,最终是调用yaffs_check_obj_details_loaded(in),将对象in的路径连接在其对应的结构上。
static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
{
u8 *buf;
struct yaffs_obj_hdr *oh;
struct yaffs_dev *dev;
struct yaffs_ext_tags tags;
int result;
if (!in || !in->lazy_loaded || in->hdr_chunk < 1)
return;
dev = in->my_dev;
buf = yaffs_get_temp_buffer(dev);
result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags);
if (result == YAFFS_FAIL)
return;
oh = (struct yaffs_obj_hdr *)buf;
yaffs_do_endian_oh(dev, oh);
in->lazy_loaded