* 内容速览 *
本文在存储的大背景下,对SPDK加速NVMe SSD后端存储应用的原理进行了简单分析,并对其主要应用场景进行了总结。同时,本文给出了SPDK相关的性能测试、项目开发、论坛交流等介绍,适宜初学者快速了解SPDK项目。
1
从hello world开始
Hello world基本是大部分程序员写下的第一个小程序。
#include <stdio.h>
int main()
{
FILE *fp = NULL;
fp = fopen("/home/test.txt","w");
if(fp)
{
fprintf(fp, "hello world\n");
}
fclose(fp);
return 0;
}
上述程序会在/home/目录下创建test.txt文件,并写入hello world字符,那么程序是怎样完成这一工作的。
我们知道home目录本质是我们挂载到计算机中的一种存储设备,这种文件目录的层次结构存储,称为文件存储。操作系统中的文件系统会负责把用户文件持久化地保存在磁盘中,即使断电,存储的内容也不会丢失,实际上文件系统可以理解为对存储设备中的文件进行组织管理,组织的方式不同就会存在有不同的文件系统。为了完成对数据的管理,文件系统分配了两个数据结构:索引节点(index node)以及目录项(directory)。索引节点记录了inode编号、数据的大小、权限、位置等信息,称之为元数据(metadata);目录项则用来存储索引节点指针、目录的层级关系,多个目录项关联起来就形成了文件系统。
需要指出的是,元数据持久化存储在磁盘中,占据一定的存储空间。在Linux系统中,基于一切皆文件的设计理念,不仅仅是普通文件受到文件系统的管理,其他例如socket,块设备等也是交由文件系统进行管理,因此在Linux系统中存储系统可以简单地分为本地存储系统和基于网络的远程存储系统,因为远程存储系统本质是通过socket,返回了一个文件描述符。
图1. 远程存储系统
在现代操作系统框架下,程序运行在目态和管态,也就是用户态和内核态,显而易见,我们编写的用户程序运行在用户态,而挂载在计算机中的存储设备属于外设的一种,操作存储设备的行为则需要进入到内核态,因此运行在用户态的程序本身不具备操作外设的条件,尽管某些技术会提供直接操作的接口,但一般说来,为了访问到外设进行读写操作(I/O),用户态程序需要通过系统调用(system call)进入到内核中,上述代码中,fopen(),fclose()是C库函数暴露给用户的接口,在打开了一个文件以后,返回了文件描述符。
图2. 系统调用过程
用户程序通过系统调用进入到内核中的虚拟文件系统(virtual file system,VFS),虚拟文件系统的本质是对各个文件子系统的封装,封装以后方便对不同的各个文件子系统进行统一的管理,VFS在收到了某个文件系统的I/O命令以后,通过对应的文件系统下发到统一的块设备层,再借由各个设备的驱动,实现相关的I/O操作。在上述代码中,我们将hello world字符进行存储,其存储大小在字节(B)量级。然而,如果以字节作为每次读写的操作单元的话,读写的效率会非