DFTL算法代码实现追加

DFTL算法中callfsim函数中的操作

原仿真器中针对DFTL中的callFsim的函数实现DFTL的部分SLRU操作:
即在DFTL的SDRAM中的映射项关系(lpn—>ppn)每一项在缓存的滞留是按LRU原则进行组织的:
SLRU的处理方式:

  1. 将缓存划分未两个区域:Ghost队列和Real队列
  2. 初次加载的最新的映射关系被保留在Real队列
  3. 当Real队列中满时,需要进行剔除,剔除后的映射关系并不直接回写入NADN中保存,而是转移到Ghost队列中进行暂存
  4. Ghost中的映射项,再满足一定条件时也会跻身再次进入到Real队列中,将Real队列中的LRU位置的映射关系置换到Ghost队列中去.
  5. Ghost队列中的LRU位置的映射在满的时候会被直接剔除,如果发生了写更新,即SDRAM中的映射关系和底层的映射关系不一致话的,则需要旧的映射关系读出来,将新的映射关系更新到NAND中

结合代码理解
根据Flashsim源码中关于DFTL的实现是分两部分的,关于在缓存部分的CMT和GTD的更新是在callFsim函数中实现的,对底层的回写,数据更新,映射关系更新回底层,垃圾回收,数据加载则在对应的dftl.c的文件中实现。本小节是针对callFsim中的实现部分做一个大致的理解解说,方便代码的理解移植。
DFTL的CMT也就是各个映射关系项的管理是采用SLRU的方式,缺失的映射关系第一次被加载入缓冲区的时候,会被加载入Real队列,当Real队列中的数据满的时候会剔除LRU(尾部)的映射项带Ghost队列中去,当Ghost队列再次被访问的时候,也有机会重新进入到Real队列中去。
在实际代码实现的过程,LRU的实现不是以链表的方式实现的,而是通过标识每个映射关系项加载的时间作为参考的,时间越大说明该映射项越新(因为每一次请求的处理,加载映射关系项,总的系统时间计数是不断增大的过程)即位于队列的MRU位置,时间越小则表示位于队列的LRU(尾部)。
具体的代码实现是为每个数据项都添加了一个age项。
因为SLRU采用的是双LRU队列,即Real队列和Ghost队列,两个队列之间必不可少地需要进行数据迁移交换:

  • (1)当Real队列满的时候,会将Real队列LRU位置的映射项移入Ghost队列中去,至于移动到什么位置是不确定的,因为LRU实现是根据各自的age大小排列组织的
  • (2)当Ghost队列中数据项再次被命中的时候,其数据项对应的age会增大,但是只是在其原来的age上+1(这里就很奇怪了,居然不是先找到Ghost最大的age,在其age值上+1,根据以往的LRU原则),同时更新完age也会和Real队列LRU位置的(最小age数据项的进行比较),如果Ghost的命中的age大于其LRU的age的值,就会将两者的位置进行交换。
  • (3)加载新的映射项到缓冲区的时候,即添加到Real的时候,是直接添加到Real队列的LRU位置,也就是先找到最大的age项,取其age值加1更新为添加项的age。但是其再次命中的时候,也只是针对其age普通的加一,并不是在最大的age的基础上进行更新,只是判断其age值是否超过了当前real_max,则更新

其代码逻辑主要如下:

  • (1)首先判断是否命中CMT中的映射项,如果命中则执行步骤(2),反之执行步骤(5)
  • (2)将命中的映射项的age在原来的基础上加1,判定命中的是Ghost还是Real队列,如果命中的是Ghost队列则执行步骤(3),反之执行步骤(4)
  • (3)判断当前命中的映射项的age是否大于Real队列LRU位置的映射项的age,如果大于则执行步骤(4),反之执行步骤(10)
  • (4)将Ghost命中的映射项和Real队列的LRU的映射项进行交换,执行步骤(10)
  • (5)判断当前的Real队列是否满,如果满了则执行步骤(6),否则执行步骤(9)
  • (6)判断当前的Ghost队列是否满了,如果满则执行步骤(7),否则直接执行步骤(8)
  • (7)找到当前Ghost队列中age最小的进行剔除(即LRU位置的映射项),这里涉及到映射项的回写更新(先读出旧的翻译页,再重新写入更新新的翻译页),Ghost队列就腾出新的位置,之后执行步骤(8)
  • (8)找到Real队列中最小age的项,将其移入到Ghost队列中去,之后执行步骤(9)
  • (9)从底层NAND中读取映射项到缓冲区(应该是整个翻译页),加载到Real队列的LRU位置,执行步骤(10)
  • (10)判断请求的类型,如果是写请求,则对其映射项的update标识位进行更新标识(置位1),之后将请求直接交由send_flash_request进行数据页的读写更新处理

这里有个地方需要十分注意的是,对映射项的查询只是查询,缓冲区的映射项的命中并不会直接更新其update的标识符,之后对应的逻辑页(blkno)请求是写请求,才会更新对应的缓冲区映射项的update的标识符。所以callFsim中关于DFTL的代码也仅仅涉及到映射关系(CMT)的加载剔除,GTD的更新。

热评文章