源代码及NVMe协议版本
-
SPDK : spdk-17.07.1
-
DPDK : dpdk-17.08
-
NVMe Spec: 1.2.1
1. 识别NVMe固态硬盘的方法
NVMe SSD是一个PCIe设备, 那么怎么识别这种类型的设备? 有两种方法。
方法1: 通过Device ID + Vendor ID
方法2: 通过Class Code
在Linux内核NVMe驱动中,使用的是第一种方法。而在SPDK中,使用的是第二种方法。 上代码:
-
src/spdk-17.07.1/include/spdk/pci_ids.h
52 /**
53 * PCI class code for NVMe devices.
54 *
55 * Base class code 01h: mass storage
56 * Subclass code 08h: non-volatile memory
57 * Programming interface 02h: NVM Express
58 */
59 #define SPDK_PCI_CLASS_NVME 0x010802
而Class Code (0x010802)在NVMe Specification中的定义如下:
2. Hello World
开始学习一门新的语言或者开发套件的时候,总是离不开"Hello World"。 SPDK也不例外, 让我们从hello_world.c开始, 看一下main()是如何使用SPDK/NVMe驱动的API的,从而帮助我们发现使用NVMe SSDs的主逻辑,
-
src/spdk-17.07.1/examples/nvme/hello_world/hello_world.c
306 int main(int argc, char **argv)
307 {
308 int rc;
309 struct spdk_env_opts opts;
310
311 /*
312 * SPDK relies on an abstraction around the local environment
313 * named env that handles memory allocation and PCI device operations.
314 * This library must be initialized first.
315 *
316 */
317 spdk_env_opts_init(&opts);
318 opts.name = "hello_world";
319 opts.shm_id = 0;
320 spdk_env_init(&opts);
321
322 printf("Initializing NVMe Controllers\n");
323
324 /*
325 * Start the SPDK NVMe enumeration process. probe_cb will be called
326 * for each NVMe controller found, giving our application a choice on
327 * whether to attach to each controller. attach_cb will then be
328 * called for each controller after the SPDK NVMe driver has completed
329 * initializing the controller we chose to attach.
330 */
331 rc = spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL);
332 if (rc != 0) {
333 fprintf(stderr, "spdk_nvme_probe() failed\n");
334 cleanup();
335 return 1;
336 }
337
338 if (g_controllers == NULL) {
339 fprintf(stderr, "no NVMe controllers found\n");
340 cleanup();
341 return 1;
342 }
343
344 printf("Initialization complete.\n");
345 hello_world();
346 cleanup();
347 return 0;
348 }
main()的处理流程为:
001 - 317 spdk_env_opts_init(&opts);
002 - 320 spdk_env_init(&opts);
003 - 331 rc = spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL);
004 - 345 hello_world();
005 - 346 cleanup();
-
001-002,spdk运行环境初始化
-
003,调用函数spdk_nvme_probe()主动发现NVMe SSDs设备。 显然, 接下来我们要分析的关键函数就是spdk_nvme_probe()。
-
004,调用函数hello_world()做简单的读写操作
-
005,调用函数cleanup()以释放内存资源,detach NVMe SSD设备等。
在分析关键函数spdk_nvme_probe()之前,让我们先搞清楚两个问题:
-
问题1: 每一块NVMe固态硬盘里都一个控制器(Controller), 那么发现