您是第 位访客

flashsim 源码分析(五): flashsim 的初始化

flashsim 的配置

flashsim 的源码目录下有个 ssd.conf 文件,对于 SSD 的一些参数可以在这个文件里面进行设置。还有一些默认的参数会在 ssd_config.cpp 文件中作为全局变量进行设置。

当需要模拟一个 SSD 时,首先需要调用 load_config(), 这个函数会读取配置文件,将配置文件中的信息保存在一些全局变量中。

flashsim 的初始化

读取配置文件后需要调用 new Ssd() 来创建一个 ssd 对象,然后就可以对这个 ssd 发送请求了。

Ssd 对象的构造函数默认会传入 SSD_SIZE 参数,这是在配置文件中进行设置的,表示的是该 ssd 包含多少个 package 。

在 ssd 对象的构造函数中会同时初始化 Controller, Ram, Bus, Channel, Package 等对象。

Controller 对象的初始化中会初始化一个指定的 FTL 对象。Controller 对象还有个 parent 属性,存储的是创建这个 controller 对象的对象(也就是某个 ssd 对象)。

Bus 对象的初始化中会初始化一定数量的 Channnel 对象。具体初始化多少个 Channel 对象,这取决于一个 bus 上 channel 的数量。bus 对象将这些 Channel 对象是放在一个叫作 channels 的数组中,数组的大小为 channel 的数量,数组中的每一个元素都是一个 channel 对象(注意:是对象,不是对象的指针)。channels[] 是作为 bus 对象的一个属性,保存在 bus 对象中。

ssd 的初始化中还会初始化一定数量的 package 对象。ssd 对象中有一个 data 数组,数组的每一个元素都是一个 package 对象。

ssd, package, die, plane, block 的对象中都有一个 data 数组,数组中存放的分别是一组的 package, die, plane, block, page 对象。也就是说, ssd 的 data 数组中存放的是一组 package 对象, package 的 data 数组中存放的是一组 die 对象,die 的 data 数组中存放的是一组 plane 对象,plane 的 data 数组中存放的是一组 block 对象,block 的 data 数组中存放的是一组 page 对象。

反过来,page, block, plane, die, package 的对象中都有一个 parent 属性,存放的是创建这个对象的对象,也就是说他们中存放的分别是创建他们的 block, plane, die, package, ssd 对象。

ssd 中一个 package 下的所有 die 共享一个 channel,所以 package 对象与 channel 应该是一一对应的。bus 对象上的 channel 对象的数量和 package 的数量是相等的。 所以当创建一个 package 对象时应该给他传递一个 channel 对象的参数(这个channel应该是bus上channel对象中的一个),这样当该 package 创建它的 die 对象时,就可以给这个 die 对象的 channel 属性赋值,这样就可以确定这个 die 是在哪个 channel 上。

初始化信息的输出

当我们 load_config() 导入配置文件,在用 new Ssd() 创建一个 ssd 对象之后,在内存中就会创建跟这个 ssd 相关的很多对象和属性,我们可以打印出这些对象的信息,从而知道在 ssd 对象的初始化的过程中程序具体干了些什么。

SSD 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{ size = 1, #该ssd上package的数量
controller = { # controller对象
stats = { numFTLRead = 0, numFTLWrite = 0,
numFTLErase = 0, numFTLTrim = 0, numGCRead = 0, numGCWrite = 0,
numGCErase = 0, numWLRead = 0, numWLWrite = 0, numWLErase = 0,
numLogMergeSwitch = 0, numLogMergePartial = 0, numLogMergeFull = 0,
numPageBlockToPageConversion = 0, numCacheHits = 0, numCacheFaults = 0,
numMemoryTranslation = 0, numMemoryCache = 0, numMemoryRead = 0,
numMemoryWrite = 0 },
ssd = @0x638250, #创建该 controller 对象的ssd对象
ftl = 0x638350 #该controller对象对应的 ftl 对象的地址。
},
ram = { read_delay = 0.01, write_delay = 0.01}, #RAM对象只有两个属性,读写一个page的延迟
bus = { num_channels = 1, # 该bus上channel的数量
channels = 0xb3a590 # channel对象数组的起始地址
},
data = 0xb4a5f0, # package对象数组的起始地址
erases_remaining = 100000,
least_worn = 0,
last_erase_time = 0
}

channel 对象

1
2
3
4
5
6
7
8
9
{ timings = std::vector of length 0, capacity 4096, #一个vector,初始化大小4096,存放的是一组占用channel的请求
table_entries = 0,
selected_entry = 0,
num_connected = 2,
max_connections = 8,
ctrl_delay = 2,
data_delay = 10,
ready_at = -1
}

package 对象

1
2
3
4
5
6
7
8
{
size = 2, # 一个package上die的数量
data = 0xb4a630, # plane对象数组的起始地址
parent = @0x638250, # 创建该package对象的对象(即某个ssd对象)
least_worn = 0,
erases_remaining = 100000,
last_erase_time = 0
}

die 对象

1
2
3
4
5
6
7
8
9
{
size = 2,
data = 0xb4a6b0,
parent = @0xb4a5f0,
channel = @0xb3a590, # 该die对应的channel对象,是bus.channels对象数组中某一个
least_worn = 0,
erases_remaining = 100000,
last_erase_time = 0
}

plane 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
size = 256,
data = 0xb4a7a0,
parent = @0xb4a630,
least_worn = 0,
erases_remaining = 100000,
last_erase_time = 0,
reg_read_delay = 0.01,
reg_write_delay = 0.01,
next_page = { package = 0,
die = 0,
plane = 0,
block = 0,
page = 0,
real_address = 0,
valid = ssd::PAGE
},
free_blocks = 256
}

block 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
{ physical_address = 0,
pages_invalid = 0,
size = 64,
data = 0xb4f7b0,
parent = @0xb4a6b0,
pages_valid = 0,
state = ssd::FREE,
erases_remaining = 100000,
last_erase_time = 0,
erase_delay = 2000,
modification_time = -1,
btype = ssd::LOG
}

page 对象

1
2
3
4
5
{ state = ssd::EMPTY, # page的状态,empty, invalid 或者 valid
parent = @0xb4a7a0, # 创建该 page 对象的对象(即某个 block 对象)
read_delay = 25, # 读一个page的延迟(us)
write_delay = 300 # 写一个page的延迟(us)
}


推荐阅读

flashsim 中的面向对象设计

flashsim 的 UML 图