PMDK 和 SNIA 标准
前面我们多次谈到的 PMDK 是 Intel 主导设计开发的,加上 Intel 对 NVM 设备的推广和 发布比较多,容易让人误以为 PMDK 只适合 Intel 的硬件。实际上当然不是这样的,在 pmem.io 网站中对此也有说明1。照录如下:
PMDK is vendor-neutral, started by Intel, motivated
by the introduction of Optane DC persistent memory.
PMDK will work with any persistent memory that provides
the SNIA NVM Programming Model. It is open source and
welcomes community contributions.
既然 PMDK 不仅仅适用于 Intel 的硬件,是厂商中立的,我们就很有必要熟悉一下其背后 的标准 SNIA NVM Programming Model。
SNIA 是个什么机构
SNIA 的全称是 Storage Networking Industry Association,是一个致力于开发标准和 教育项目以推进存储和信息技术的非盈利性组织2。SNIA 的会员总数接近 200 个,包括了 CPU、存储设备、服务器、网络等领域的知名企业和学术机构。SNIA 制定了很 多知名的标准,例如 Cloud Data Management Interface (CDMI)、Linear Tape File System (LTFS)、NVM Programming Model (NPM)、Storage Management Initiative Specification (SMI-S) 等等。SNIA 甚至也实现了一些知名标准的参考实现,例如著名的 NDMP V4、XAM SDK。
SNIA NVM 编程模型
SNIA NVM 编程模型(The NVM Programming Model, NPM)推出的目的就是为了推广 NVM 技术的落地。要将一种新存储设备集成到现有生态中是一个特别大的工程,需要众多软硬件 厂商的持续多年的努力和合作。NPM 定义了用户态和内核态不同组件之间的推荐行为,但是 并没有定义具体的 API。可以看出,标准的目的还是以约定行为为主要目的,而不是定义得 很细。这也符合一个新技术产生和发展的进程,不太可能在新出现的时候就比很多细节想清 楚,而且定义得过细也会限制了厂商的技术创新。新技术的发展还是要靠整个生态的推动和完善。
NPM 有三个主要的版本,v1 是 2013 年底发布的,v1.1 是 2015 年三月份发布的,最新的 v1.2 是 2017 年六月份发布的3。
NPM 的主要内容
从使用 NVM 设备的角度看,我们不需要关心 NPM 中的很多细节,可以重点关注各种设备都 支持的公共特性;如果对某种特定的 NVM 设备使用甚至编程,更推荐参考特定的厂商文档 以及 PMDK。
首先,NVM 设备可以用作块设备或者 PM 设备。而且一个 NVM 设备可以被划分成多部分, 分别用作块设备或者 PM 设备。从编程的角度看,既然 NVM 设备可以被当做块设备,应用 就可以直接访问它,也可以通过在块设备上创建文件系统,然后通过标准的文件系统 API 来进行访问。类似的,NMV 用作 PM 设备时,也可以被视为一个块设备或通过文件系统来访 问。但是通过文件系统访问时,如果文件系统实现了对应的功能特性,就可以不用文件系统 的 PAGE CACHE,而是直接访问 NVM 设备,更进一步,就不需要 FSYNC 这样的接口来同步 刷新数据了。应用程序可以通过之前我们介绍过的 PMDK 中的 MMAP 接口和 SYNC 等接口进 行数据的读写和刷新。
而对于很多具体的涉及硬件设备特性的问题,NPM 都没有给出具体的要求,而是交给可厂商 去做定义。例如介质故障的检测和处理、MMAP 的内存读写出错时的处理。同样的,对于持久域、操作的对齐等问题,也都需要和具体的硬件平台去定义。
NPM 的大部分篇幅(第7到第10章)都是按照不同的使用模式去说明了 ACTIONS(可以大致 对应到 API)、ATTRIBUES(可以大致对应到特性和能力参数)、USE CASE(使用场景), 可以根据实际需要去查阅。下面以第 10 章 NVM.PM.FILE 为例,简要说明 NPM 的内容。
NVM.PM.FILE
这种模式允许用户态应用程序把 NVM 设备当做内存来访问,与此同时,应用程序用的还是 文件系统的 API。显然,这样有很多好处,可以复用现有的文件系统 API,减少应用程序修 改的难度;同时也意味着不是什么文件系统都支持 NVM,它们需要针对 NVM 设备做一些修 改,Linux 上的 XFS、EXT4 以及 Windows 上的 NTFS 都支持了 NVM 设备的这种用法。详 情可参考下图:
NVM.PM.FILE 模式下特有的 API 为 NVM.PM.FILE.MAP 和 NVM.PM.FILE.SYNC, 也就是 PMDK 中的 pmem_map_file() 和 pmem_persist()。
如果不考虑 NVM 的持久性,这种模式下 NVM 的特性保持与内存一致,例如针对内存操作的 原子性保证、各级 CPU CACHE 以及可见性保证等都与内存一致。
对于块设备而言,读写出错的时候可以自然的知道出错的 IO 对应的文件位置和数据块,并 因此做一些对应的错误处理。尽管要处理好各种错误也不是那么的容易。对于内存设备而言, 读写出错意味着内存地址出错,Linux 上也就是 SIGBUG 信号,应用程序只能在信号处 理函数中做一些处理。无论是块设备还是内存设备,介质本身的错误只能依靠管理命令来修 复。对于内存设备而言,还需要管理命令做更多的支持,不然应用程序再次访问出错的内存 地址就会又触发 SIGBUS。10.4 Use cases 有一些具体场景使用场景和错误处理的代码片段, 可供参考。
Footnotes
3 https://www.snia.org/tech_activities/standards/curr_standards/npm