‹ 返回视频系列: 持久内存编程入门

持久内存编程(第 2 节)NVM 编程模型

  • 概览
  • 资源
  • 文字稿

英特尔的 Andy Rudoff 为您介绍持久内存,并解释为什么最近它在业界如此热门。Andy 将描述持续内存是如何与计算机平台连接的,它是如何工作的,以及编程人员面临的一些挑战。Andy 是一位非易失性内存软件架构师,也是存储网络行业协会 ( SNIA) 非易失性内存编程技术工作组的成员。

大家好,我是英特尔公司的 Andy Rudoff。本视频将讲解适用于持久内存的 SNIA NVM 编程模型。这种方式有助于操作系统向应用程序提供持久内存。请记得观看持久内存编程播放列表中的后续内容,我们将继续讲解这个模型。

让我们了解一下关于持久内存编程的基本概念。作为一名编程人员,您可能很熟悉存储器软件堆栈,这里显示的是一个非常高的级别。在几十年的使用过程中,组成软件堆栈的这些基本块并没有太大的变化。应用程序使用标准文件 API 打开文件系统中的文件,而文件系统通过一个或一系列驱动程序根据需要执行块的 I/O 操作。所有对存储器的访问都发生在块中,通常采用 PCIe 等互联接口。到目前为止,我并没有提到具体的操作系统,因为在这个高度上,它们都极其相似。

如果您是一位 Windows 或 Linux 编程人员,可能会意识到这些用于打开文件和读写各种数据的基本 API 现在都已经超过 30 年了。也许您从未使用过这些调用,因为您习惯于使用库进行编程,库中提供了更方便的 API。而这些库最终会在内部调用这些基本的 API。Windows 和 Linux 都支持内存映射文件,这一功能已经存在很长时间了,但并不常用。对于持久内存,这些用于内存映射文件的 API 非常有用。事实上,它们是存储网络行业协会 (SNIA) 发布的持久内存编程模型的核心。

只有当已经打开一个文件之后,才允许对该文件进行内存映射,所以当应用程序在 Windows 上调用 CreateFileMapping 和 MapViewOfFile 或在 Linux 上调用 nmap 时,已经执行过权限检查。一旦执行这些调用,该文件就会出现在应用程序的地址空间中,允许对文件内容进行加载和存储访问。内存映射文件有一个重要的特征,即通过存储指令所做的更改在刷新到存储器之前并不能保证其持久性。在 Windows 系统中,使用 FlushViewOfFile 和 FlushFileBuffers 进行刷新。在 Linux 系统中,我们使用 msync 或 fsync。内存映射文件使该文件好像安排在应用程序的虚拟内存中。应用程序只是使用指针对存储器中的数据结构进行加载和存储操作。

从应用程序的角度看,这是字节可寻址存储器。但存储器中真正发生的操作是分页调度。分页调度是操作系统将程序暂停,对存储器执行 I/O 操作。存储器只能以块为单位执行 I/O 操作。因此当程序首次访问一个文件中的一个字节时,会从存储器读取一个完整的块(通常为 4k 字节)。当程序将一处修改刷新为持久性时,它必须等待操作系统写出完整的块。这就是内存映射文件 API 的强大功能为持久内存编程带来的真正优势。

标准文件 API 的工作原理是一样的。但如果使用持久内存,会使用一个持久内存感知文件系统来设置内存映射文件。其结果是对持久媒介直接进行加载和存储访问,而不是使用传统存储所实现的分页访问。看看传统的堆栈如何将所有内容转换成块访问。持久内存编程模型允许对接入内存总线的非易失性媒介进行字节级访问,这里以常见的行业术语 NVDIMM 表示。

您可以看到,一旦设置了映射,应用程序就获得了由 MMU 的虚拟到物理映射所提供的直接访问权限。这种将这些直接映射配置到持久内存的功能被称为 DAX,这是直接访问 (direct access) 的缩写。是否支持这个功能是区分普通文件系统和持久内存感知文件系统的关键因素。目前 Windows 和 Linux 都支持 DAX。

现在您已经了解了操作系统如何将持久内存提供给应用程序。请观看此播放列表的后续内容,了解当应用程序取得大范围访问持久内存的权限之后将会发生什么。感谢您观看这段视频和持久内存编程播放列表。记得访问下方提供的链接。别忘了订阅和为视频点赞。