热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Yaffs文件系统

Yaffs文件系统挂载流程初始化与VFS层的接口:sb-s_op&yaffs_super_ops;inode-i_op&yaffs_file_inode_op

Yaffs文件系统


挂载流程


  1. 初始化与VFS层的接口:
    sb->s_op = &yaffs_super_ops;
    inode->i_op = &yaffs_file_inode_operations;
    inode->i_fop = &yaffs_file_operations;
  2. 初始化与驱动层的接口:

param->write_chunk_tags_fn = nandmtd2_write_chunk_tags;param->read_chunk_tags_fn = nandmtd2_read_chunk_tags;param->bad_block_fn = nandmtd2_mark_block_bad;param->query_block_fn = nandmtd2_query_block;param->erase_fn = nandmtd_erase_block;param->initialise_flash_fn = nandmtd_initialise;

  1. 初始化yaffs_dev结构:
    主要在yaffs_gus_initialise函数完成,具体包含以下部分:
    初始化擦除块信息:yaffs_init_blocks
    初始化cache和buffer:yaffs_init_tmp_buffers
    初始化tnode和objs:yaffs_init_tnode_and_objs
    初始化根目录:yaffs_create_initial_dir
  2. yaffs2_checkpt_restroe流程:
    -> 基础设施搭建完毕,后面就是扫描falsh内存中建立完整的文件试图,YAFFS2首先尝试从checkpoint中恢复文件系统的信息
    -> yaffs2_rd_checkpt_open 为读出checkpoint信息做一些初始化工作,首先创建一个checkpt_buffer,初始化checkpt_block_list数组
    -> yaffs2_rd_checkpt_validity_marker读取checkpoint头部信息,并判断是否正确
    -> yaffs2_rd_checkpt_dev读取struct yaffs_checkpt_dev结构的信息,用来填充yaffs_dev结构相应的字段,以及flash上各个擦除块yaffs_block_info信息,还有chunk_bits表示flash上各个chunk位图
    -> yaffs2_rd_checkpt_validity_marker读出checkpoint尾部信息,并判断是否正确
    -> yaffs2_rd_checkpt_sum读出校验和,并和计算的比较是否一致
  3. yaffs2_scan_backwards流程:
    如果上述5个步骤都没有错误,则从checkpoint挂载成功,否则就扫描整个flash
    -> 扫描整个flash OOB信息,按照bi->seq_number顺序对block进行排序
    -> 其次从seq_number最大的block开始往seq_number减小的方向扫描
    -> 最后从physical_chunk_index大的chunk开始,并向减少的方向扫描
    -> 读取chunk的tags信息,根据tags.chunk_used判断chunk是空闲的还是被使用:根据tags.chunk_id判断是data_chunk,还是object header
    -> 如果是data chunk,分几种情况:
    a. 根据tags.obj_id查找散列表,找到object对象,则把tags.chunk_id转转成文件的偏移,拿这个偏移和文件对象的shrink_size加入到对应的tnode_tree中,否则删除该chunk:这个一般发生在正常关闭文件的情况下,也即先扫描到到object header,后扫描文件的data chunk,这种情况文件的实际大小应该由扫描碰到的第一个object header所记录的大小的决定
    b. 根据tags.obj_id查到散列表,不存在则创建新的object对象,并插入到散列表中,则把tags.chunk_id转换成文件内的偏移,拿这个偏移和文件对象的shrink_size比较,如果在文件的大小范围内则调用yaffs_put_chunk_in_file把该chunk加入到对应的tnode tree中,否则删除该chunk,这一般发生在非正常文件的情况下,也即先扫描到data chunk,后扫面到文件的object header,这种情况文件大小由扫描到的第一个data chunk决定
    -> 如果是object header,分几种情况:
    a. object header被扫描到,object散列表中并无对应的文件,那么根据tags.obj_id、tags.extra_obj_type或者tags.oject_type或者tags.obj_id、oh->type创建新的object对象,并使用object header的信息初始化object对象,并根据oh->parent_obj_id创建父object对象,把二者联系起来
    b. object header被扫面到,object散列表中已经存在对象的object对象,且对象已经有关联的object header,说明这个object head是过时,所以就直接删除该chunk

打开流程

YAFFS文件的打开主要由yaffs_iget函数完成:
根据yaffs_obj的信息填充inode:
inode->i_size = obj->variant.file_variant.file_size;
indoe->i_ino = obj->obj_id;
如果是普通文件:

inode->i_op = &yaffs_file_inode_operations;inode->i_fop = &yaffs_file_operations;inode->i_mapping->a_ops = &yaffs_file_address_operations;

如果是目录文件:

inode->i_op = &yaffs_dir_inode_operations;inode->i_fop = &yaffs_dir_operations;

读取流程

YAFFS2文件的读取主要由yaffs_readpage函数完成:根据pg->index计算文件内偏移,然后转换成logical chunk index,最后在Tnode tree中找到相应的physical chunk index,读取该chunk的数据到页缓存中
读取的过程涉及到YAFFS2内部的cache,首先检测读取的数据是边界否chunk对齐,大小是否data_bytes_per_chunk对齐,如果边界对齐就是不需要内部的cache,如果有就直接从cache读取,没有对应的cache则分配一个cache。从chunk中读取cache中,然后再从cache到页缓存中


写入流程

YAFFS2文件的写入操作主要由yaffs_file_write函数完成:根据pg->index计算文件内偏移,然后转换成logical chunk index:然后分配空闲chunk,建立logical chunk index和physical chunk index,把页缓存中的写入数据到分配的chunk,并把chunk插汝到tnode tree
写入的流程页涉及到YAFFS内存的cache,首先检测写入的数据是否边界chunk对齐,大小是否data_bytes_per_chunk对齐,如果边界对齐就不需要内部的cache直接从页缓存写入chunk中,否则再cache查找该文件是否有对应的cache,如果有就直接写入cache中,如果cache中的数据达到data_bytes_per_chunk就同步到flash;没有对应的cache则分配一个cache,chunk中读取cache中,然后再把数据写入cache中


删除流程

YAFFS2文件的删除采取软删除主要由yaffs_unlink函数完成,对于不同的文件具体划分:普通文件对应yaffs_del_file函数,目录文件对应yaffs_del_dir函数。普通文件如果对应的有数据即n_data_chunk大于0,则把文件移到unlink目录,并释放内存中tnode tree,in->deleted置1,obj_dirty置1,obj->unlinked置1,并写入一个新的object header,oh->file_szie = 0,chunk留待垃圾回收擦除;如果没有对应 的数据则把文件移到deleted目录,则删除空的tnode tree,最后释放object,并写入一个新的object header,oh->file_szie = 0。目录文件比较简单,最后释放object,并写入一个新的object header表示文件被删除


垃圾回收


  1. 回收时机
    -> 在yafffs_wr_data_obj入口调用yaffs_check_gc进行垃圾回收
    -> 在yaffs_bg_thread_fn垃圾回收线程中进行回收,该线程会定时被唤醒,根据剩余空间的多少,定时间隔会动态调整,该线程是非实时的,最后调用yaffs_check_gc进行垃圾回收
  2. 回收策略
    根据空闲擦除块的数量判断空间是否紧张,分为如下两种策略:
    ->aggressive garbage collection,比较紧急的回收,yaffs_find_gc_block找到符合条件的擦除块条件比较宽裕,具体体现以下两个指标的计算上:

/* 表示擦除块dev->gc_page_in_use的阈值,这个阈值越大擦除块越好选择 */threshold = dev->param.chunks_per_block;/* 表示选择擦除块的范围,比较紧急的时候要搜索所有的擦除块找合适 的进行回收 */iterations = dev->internal_end_block - dev->internal_start_block + 1;

->“leasurely” garbage collection,非紧急的回收,yaffs_find_gc_block找到符合条件的擦除块条件比较严格,具体体现在以下两个指标的计算上:

/* 表示找全脏的,无效chunk的块进行回收 */threshold = background ? (dev->gc_not_done + 2) * 2 : 0;/* 表示只在很小的范围内搜索这样的擦除块 */iterations = (dev->internal_end_block - dev->internal_start_block + 1) / 16 + 1;

  1. 回收过程
    -> 首先选择合适进行回收的擦除块,由yaffs_find_gc_block来完成,当block不包含shrink flag时,则它适合gc;如果擦除块包含shrink flag标志,则已完成chunk分配且最早被使用的block合适gc
    -> 如果该擦除块还有有效的chunk,则要将正使用的chunk挪到空闲的block上,来腾出这个比较脏的block,由yaffs_gc_process_chunk完成
    -> 当整个擦除块无有效chunk时,yaffs_block_became_dirty调用yaffs_erase_block把该擦除块擦除掉

推荐阅读
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
author-avatar
七月漂香
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有