您是第 位访客

disksim-3.0 with flashsim 源码分析(三):callFsim()函数介绍

disksim-3.0 with flashim 和前面的 disksim-4.0 with ssdmodel 在逻辑上基本相似,只是多了些 FTL 层的东西。和前面介绍的 disksim-4.0 with ssdmodel 一样,程序仍然是从 disksim_device.c 中的 device_event_arrive() 函数中进入到 ssd 模块的。

进入到 ssd 模块后首先进入的是 disksim_simpleflash.c 文件,这就类似于 disksim-4.0 with ssdmodel 中的 ssd.c 文件,他们实现的功能有很多是相同的。

最后在 simpleflash_get_acctime() 函数中调用 callFsim() 函数。callFsim() 函数以后的内容才是 flashsim 重点实现的部分。

callFsim()函数位于 ssd_interface.c 文件中,接下来重点介绍下这个函数。

callFsim()

函数形式

1
double callFsim(secno,scount,operation)

参数说明
secno: 请求的起始地址(单位是sector,512B)
scount: 请求的长度(单位是sector,512B)
operation: 请求的类型(0:读,1:写)

返回值

处理这个请求花费的时间

函数实现

首先,将 secno 和 scount 按照闪存的页大小(4KB)对齐,用blkno表示请求的起始逻辑页地址,bcount表示请求的长度是多是个页。

1
2
3
blkno = secno / SECT_NUM_PER_PAGE; // page number
blkno += page_num_for_2nd_map_table; // 低地址留给GTD,所以其他的地址都要加上一个偏移量
bcount = (secno + scount -1)/SECT_NUM_PER_PAGE - (secno)/SECT_NUM_PER_PAGE + 1; //按照页对齐

bcount 变量表达的含义是这个请求需要访问多少个页,所以需要循环 bcount 次,每次请求一个页。

每次请求一个页时,首先要查映射表,并处理和映射表相关的操作(命中或者不命中情况下的各种操作),这个在前面已经介绍过了(戳这里)。处理完映射表相关的操作后直接调用 send_flash_request(blk_no, block_cnt, operation,mapdir_flag),将请求发送到下一层。这样,针对一个页面的请求就完成了,这个过程循环 bcount 次,这个大请求也就完成了。

在所有请求结束之后,在 callFsim() 函数中会调用 calculate_delay_flash() 函数,并将 calculate_delay_flash() 的返回值作为 callFsim() 函数的返回值返回,表示的是处理整个大请求用了多少时间。

send_flash_request()

函数形式

1
send_flash_request(start_blk_no, block_cnt, operation, mapdir_flag)

参数说明

start_blk_no: 请求的起始地址(单位是sector,512B)
block_cnt: 请求的长度(单位是sector,512B)
operation: operation:请求的类型(1:读,0:写)
mapdir_flag: 请求的页的类型(0:映射页,1:数据页)

函数实现

在 send_flash_request() 函数内部会根据当前 ftl 的不同(DFTL,FAST等),调用不同的 write 或 read 函数去执行请求。

calculate_delay_flash()

ssd_interface.h 中定义了如下的变量,用以计算处理一个上层发来的大请求所耗费的时间,

1
2
3
4
5
6
7
flash_oob_read_num:读 oob 的次数
flash_oob_write_num:写 oob 的次数
flash_read_num:写闪存的次数
flash_write_num:读闪存的次数
flash_erase_num:擦除操作的次数
flash_gc_read_num:擦出操作中读的次数
flash_gc_write_num:擦出操作中写的次数

上面7个变量对应一个请求中可能发生的耗时的7种类型的操作。这七个变量是全局变量,可以在多个文件中共享。

在初始化的时候,这个7个变量全部为0,reset_flash_stat() 函数的功能就是初始化这7个变量,将它们的值全部置为0。

当上层的一个大请求处理完成之后,也就是在 callFsim() 函数的尾部会调用 calculate_delay_flash() 来计算在这个请求处理的阶段的耗时。

calculate_delay_flash() 计算耗时的原理是,将每个操作的次数乘以每个操作的耗时,然后求和。返回求和后的值。在 calculate_delay_flash() 函数返回之前还会调用一次 reset_flash_stat() 函数来重置上述7个变量的计数器,用以记录下个请求的数据。