ubifs核心功能 -- 垃圾回收


可回收空间的分类

    垃圾回收的目的是再利用(回收后的空间大小能写入有效的node),如果再利用的价值越低,其回收的必要性越低。为了进行有效的垃圾回收,UBIFS对可回收空间做了2个层次的水线划分:

    死空间水线,即最小node大小(一般是最小的data node):dead_wm = ALIGN(MIN_WRITE_SZ, min_io_size);

    暗空间水线,即最大node大小(一般是最大的inode node):dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, min_io_size);

    一般来说, min_io_size(page or subpage) <= dead_wm <= dark_wm。在我们的系统上,dead_wm和dark_wm的水线都是一个page的大小(8K)

    free + dirty < dead_wm时,此时认为垃圾很少,一般就认为此LEB full,不值得进行垃圾回收。

     free + dirty < dark_wm时,因为可回收的空间较小,dark_wm被回收的概率也变小。同时为了效率和节约空间考虑,这种leb也不会被加入到内存LPT树中。如果可回收空间小于dark_wm,这段空间的回收价值就不大。所以也得出一个结论:node越大,浪费的空间越大。

可回收对象的分类

因为index node和非index node的管理方式不一样,垃圾回收需要对这2类对象进行区分处理。

非index node的管理方式为 wbuf - flash 2层结构,比较简单。在ubifs_garbage_collect_leb(BG GC)或者ubifs_gc_start_commit(Commit GC第一阶段)阶段unmap LEB完成回收;

index node的管理方式为 TNC - journal - flash 4层结构,相对复杂。在ubifs_garbage_collect_leb(BG GC)或者ubifs_gc_start_commit(Commit GC第一阶段)阶段完成准备,在ubifs_gc_end_commit (Commit GC第二阶段)阶段unmap LEB完成回收,所有被垃圾回收的index leb加入到链表idx_gc中,这个链表中的leb在ubifs_gc_end_commit阶段unmap。

垃圾回收(后台进程阶段

后台垃圾回收由background线程负责,由wbuf定时器定时唤醒,并判断是否需要进行垃圾回收,如是,启动垃圾回收操作。正常情况下,每次垃圾回收操作回收UBIFS_GC_ONCE(5)个LEB。

回收的leb最后被unmap,并且标记为空(bud->start 设置为 0),再次使用时,会重新map。LEB unmap-map重新映射流程,UBI根据磨损均衡算法进行重新map,达到PEB磨损平衡的效果。同时也避免了反复使用一个PEB的情况。

垃圾回收时垃圾LEB上有效的数据会搬运到gc wbuf->lnum对于的LEB上,gc_lnum作为后备的垃圾回收目的LEB,如果gc的wbuf->lnum无效,取gc_lnum作为gc wbuf->lnum,并置c->gc_lnum无效(switch_gc_head)。通过gc_lnum,保证在垃圾回收时,不会出现找不到搬运目的LEB的情况(即gc wbuf->lnum)。

垃圾回收判断准则:

检查gc水线设置gc_waterline, 只有当总的脏空间lst.total_dirty > 分卷总大小/gc_waterline时,才进行GC,避免在空闲空间较多的情况下进行gc。gc_waterline默认为UBIFS_FREE_RESERVE_RATIO(5)。

而且,对于index node,ubifs对于index的回收是只回收脏空间大于一半擦除块的,其他index擦除块可能即使有脏空间也不会进行回收。

垃圾回收流程:

1)判断是否需要commit,如是,返回-EAGAIN,触发commit流程

2)已经回收了index LEB并且gc已连续尝试SOFT_LEBS_LIMIT(4)次,返回-EAGAIN

3)如果gc已连续尝试HARD_LEBS_LIMIT(32)次,返回-ENOSPC

4)查找dirty LEB进行回收(查找顺序依次是lpt_heap[LPROPS_DIRTY_IDX], lpt_heap[LPROPS_DIRTY], lpt_heap[LPROPS_FREE],c->uncat_list,LPT in flash)

5)读取dirty LEB的node,并进行排序、分类、丢弃过时数据和无需搬运数据等处理

6)搬运数据到gc wbuf对应的LEB(gc LEB),回收垃圾LEB,这里区分index LEB和非index LEB详细流程见下

7)如果回收的是非index LEB,此次GC结束

8)如果回收的是index LEB,继续GC

9)已经回收过多次还没有回收成功,说明每次回收的块都用于gc自己(因为GC需要始终占用一块free的LEB,用来作为搬运的目地LEB,即gc LEB),而且当前用于gc回收的leb空间没有更多。这里就尝试找更脏的leb,因为这样的LEB上的有效数据少,回收这样的leb需要的空间就要小些。

10)同步gc wbuf,unmap gc LEB(c->gc_lnum)

11)更新LPT树

搬运数据,回收LEB详细流程

可全部回收的 leb(free + dirty == leb_size):sync,然后unmap

1)如果不是全free的leb,将data和index wbuf写到对应的flash LEB。避免GC后,wbuf又把obsoleting nodes写入flash。然后再更新LEB lprops并将此LEB加入到c->frdi_idx_list(index LEB)或c->freeable_list(data LEB)。

2)unmap回收LEB

3)如果c->gc_lnum无效,将回收的lnum作为c->gc_lnum,然后返回LEB_RETAINED。否则返回LEB_FREED。

非index leb:搬运后再sync,然后unmap

1)将有效node搬运到GC LEB的wbuf(c->jheads[GCHD].wbuf)

2)为了保证垃圾回收的节点是存在flash的,同步data和index LEB的wbuf到flash。避免GC后,wbuf又把obsoleting nodes写入flash

3)更新LEB lprops并将此LEB加入到c->freeable_list(data LEB)

4)如果c->gc_lnum无效,将回收的lnum作为c->gc_lnum,然后返回LEB_RETAINED。否则,同步gc LEB的wbuf到flash,再unmap回收LEB,然后返回LEB_FREED。

index leb:更新idx_gc->list对象和c->frdi_idx_list对象,以备在end commit gc阶段使用

1)遍历index leb中index node,将 index node加入到TNC,并将TNC中该节点对应路径设置为脏,commit的时候就会重新写入flash,在gc中就达到了搬运的目的;

2)将此LEB加入到已经gc的index链表中 idx_gc->list。因为已经将这个index leb读取到TNC中,所以在下一次commit的时候会将这些读取到TNC中的index写入flash。但是不能立即unmap这个leb,因为commit还没有发生, 如果发生掉电,还需要保留这个index leb,用于恢复,否则发生掉电,这个index leb已经unmap,但又没有commit完成,则这个index leb上的数据就会丢失。

3)更新LEB lprops并将此LEB加入到c->frdi_idx_list(index LEB),然后返回LEB_FREED_IDX。

垃圾回收提交阶段

        提交阶段的垃圾回收,以commit为界,划分为2部分:ubifs_gc_start_commit和ubifs_gc_end_commit。

ubifs_gc_start_commit:更新idx_gc->list对象和c->frdi_idx_list对象,以备在end commit gc阶段使用

1)unmap freeable_list LEB,更新lprops;

2)找出所有的frdi_idx_list LEB,并更新到idx_gc中;

ubifs_gc_end_commit:unmap idx_gc LEB

此阶段前,已完成commit,所以可以放心地unmap所有的idx_gc LEB;

至此,UBIFS文件系统垃圾回收流程完成。

--EOF--

时间: 2024-07-31 08:18:24

ubifs核心功能 -- 垃圾回收的相关文章

第十一节:用于本地资源的其它垃圾回收功能

有时,本地资源会消耗大量的内存,但是用于包装该资源的托管对象只占用了非常少的内存.一个典型的例子就是位图.一个位图可能占用几兆字节的本地内存,但是托管对象却极小,因为它只包含了一个hbitmap(一个4或8字节的值),从CLR角度看,一个进程可以在执行一次垃圾回收之前分配数百个位图(他们用的托管内存太少了).但是,如果进程操作许多位图,进程的内存消耗将以一个恐怖的速度增长.为了修正这个问题,GC类提供了以下两个静态方法: public static void AddMemoryPressure(

深入Java核心 探秘Java垃圾回收机制(转自http://edu.21cn.com/java/g_189_859836-1.htm)

垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变.垃圾收集的目的在于清除不再使用的对象.GC通过确定对象是否被活动对象引用来确定是否收集该对象.GC首先要判断该对象是否是时候可以收集.两种常用的方法是引用计数和对象引用遍历. 引用计数收集器 引用计数是垃圾收集器中的早期策略.在这种方法中,堆中每个对象(不是引用)都有一个引用计数.当一个

2019年1月28日 18:48:10 ----怀疑DDOS或者缓存无垃圾回收功能【附带各知识来源】

今日网吧上网,打开邮件,QQ音乐速度明显比前面慢得非常多,体现出非正常反应.(HTTP,HTTPS) 观察其他机器,发现游戏正常.(TCP,UDP) 我将情况告诉网管,网管联系后台人员,后台人员进行了清理垃圾等操作以后,网速恢复正常反应 缓存垃圾回收,可以重启汇聚层的路由器交换机等.如果重启无效,那么DDOS网吧生意之争将有很大的几率发生.还有一种很大的可能,就是客户开外挂导致的网络攻击(甚至感染整个网吧的域,你的帐号信息被盗也会这样子发生). 如何发现程序及进程等底层的问题?(学术叫计算机取证

Python中的垃圾回收机制

当我们声明一个对象的时候,例如str="abcdef",当我们不再使用str这个对象的时候,这个对象就是一个脏对象,垃圾对象,但是它还在占着内存,毕竟我们的电脑内存有限,所以应该有一个机制来回收它以及类似的对象.现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++里用户自己管理维护内存的方式.自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患. 对于一个字符串.列表.类甚至数值都是对象,且定位简单易用的语言,自然不会

java语言及其垃圾回收机制简单概述

 一.java 语言概述 Java 语言是一门纯粹的面向对象编程语言,它吸收了c++语言的各种优点.又摈弃了c++里难以理解的多继承,指针等概念因此Java语言具有功能强大和简单易用两个特征. Java语言的几个重要概念如下: J2ME:主要用于控制移动设备和信息家电等有限存储设备 J2SE:整个java技术的核心和基础, J2EE:java技术中应用最最广泛的部分,它提供了企业应用开发相关的完整的解决方案. API: 核心类库 JRE:运行Java程序所必须的环境的集合,包含JVM标准实现及J

Java内存模型与垃圾回收

1.Java内存模型 Java虚拟机在执行程序时把它管理的内存分为若干数据区域,这些数据区域分布情况如下图所示: 程序计数器:一块较小内存区域,指向当前所执行的字节码.如果线程正在执行一个Java方法,这个计数器记录正在执行的虚拟机字节码指令的地址,如果执行的是Native方法,这个计算器值为空. Java虚拟机栈:线程私有的,其生命周期和线程一致,每个方法执行时都会创建一个栈帧用于存储局部变量表.操作数栈.动态链接.方法出口等信息. 本地方法栈:与虚拟机栈功能类似,只不过虚拟机栈为虚拟机执行J

垃圾回收算法和JVM垃圾收集器(一)

参考文献:深入理解Java虚拟机 周志明 Java编程思想 Bruce Eckel 为什么自动化垃圾回收后还要了解GC呢:当需要排查各种溢出.内存泄漏问题时,当垃圾收集成为系统达成更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节. 垃圾回收的主要区域:Java堆和方法区 那么,如何判断对象是否已经可以回收呢?主要有两种方法: 一.引用计数算法:每个对象都有一个引用计数器,当有引用连接至对象时,引用计数器加1:当引用计数器离开引用作用域被置null时,引用计数减1.垃圾回收

Java 垃圾回收机制概述

摘要: Java技术体系中所提倡的 自动内存管理 最终可以归结为自动化地解决了两个问题:给对象分配内存 以及 回收分配给对象的内存,而且这两个问题针对的内存区域就是Java内存模型中的 堆区.关于对象分配内存问题,笔者的博文<JVM 内存模型概述>已经阐述了 如何划分可用空间及其涉及到的线程安全问题,本文将结合垃圾回收策略进一步给出内存分配规则.垃圾回收机制的引入可以有效的防止内存泄露.保证内存的有效使用,也大大解放了Java程序员的双手,使得他们在编写程序的时候不再需要考虑内存管理.本文着重

Java虚拟机之垃圾回收详解一

Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这些程序包括:实用程序.游戏.商业应用程序.在全世界范围内,Java运行在超过数十亿台个人计算机上,数十亿台设备上,还包括手机和电视设备.Java由一系列的关键组件作为一个整体构建出了Java平台. Java Runtime Edition 当你下载Java,你就得到了Java运行环境(JRE).JR