绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
NVMe的Linux内核驱动分析
2020-07-09 16:59:34

前面两篇文章我们对NVMe的原理和涉及的主要概念进行了介绍,今天我们将介绍一下NVMe的Linux驱动是如何实现的。首先NVMe本身是一个块设备,因此NVMe的驱动也是遵循块设备的驱动架构。本文通过两部分介绍NVMe的驱动程序,一部分是操作系统如何创建NVMe块设备,另外一部分是分析一下NVMe的主要流程,包括读写流程和管理流程等。

两点说明: - 本文基于Linux 4.1.12 版本的内核进行介绍,其它版本的内核代码可能略有不同,但不影响理解。 - 在阅读本文之前,如果能够阅读一下本号之前关于块设备和SCSI的文章,对理解本文将很有帮助。

创建NVMe块设备

对于Linux的块设备来说,其主要的是通过device_add_disk或者add_disk函数(后者是对前者的简单包装)来向操作系统添加一个设备实例。具体原理我们在之前的文章中已经介绍过,本文不再啰嗦了,想了解的同学请自行翻阅一下历史文章。其基本原理就是通过调用该函数,就会创建在/dev目录下看到的类似sdX的块设备。 NVMe本身也是块设备,自然也不会跳出这个大框架。首先从硬件层面上,我们知道任何设备必须通过某个总线与CPU向连接,NVMe则正是通过PCIe总线与CPU相连

当然,目前NVMe除了可以通过PCIe总线与CPU相连外,还可以通过其它通道连接,比如FC或者IB。后者则是一种将NVMe设备从计算节点独立出来的方式,也就是此时NVMe就不再是一个卡设备,而是一个独立机箱的设备。无论何种方式相连接,其本质是一样等。 然后是操作系统软件层面的内容。硬件的连通性是基础,当硬件已经连通后,就可以在Linux内核层面发现设备,并进行初始化了。软件层面的初始化有两种情况,一种是计算机启动的时候,操作系统会扫描总线上的设备,并完成初始化;另外一种情况是设备在系统启动后连接的,此时需要手动触发扫描的过程。 无论是系统启动也好,还是手动触发扫描也好,NVMe发现设备的核心流程是一样的。

与其它块设备类似,NVMe设备初始化完成后会在/dev目录下出现一个文件。NVMe设备会出现一个形如nvmeXnY的设备文件。如图3所示,红色方框中的为一个NVMe块设备。

核心实现分析 上面我们简要的介绍了初始化的主流程。在上面初始化流程中需要重点关注的是nvme_alloc_ns函数的流程。该函数完成了块设备创建、基本信息填充和块设备注册到内核等工作。如图4是该函数的部分代码片段。这部分片段完成了函数指针的初始化、命令队列初始化和设备名称的初始化等工作。具体关于nvme_alloc_ns函数源代码的逻辑请自行阅读代码,本文不再赘述。

在整个初始化流程中比较关键的是对请求队列(request_queue)中请求处理函数指针(make_request_fn)的初始化及多队列函数集(mq_ops)的初始化。因为,这里的函数正是NVMe区别于SCSI等类型设备数据处理流程的地方。

NVMe设备的IO流程

为了便于理解NVMe的处理流程,我们给出了传统SCSI及NVMe数据处理的对比流程。如图5所示,整个流程是从通用块层的接口(submit_bio)开始的,这个函数大家都非常清楚了。

对于NVMe设备来说,在初始化的时候初始化函数指针make_request_fn为nvme_queue_rq,该函数就是NVMe驱动程序的请求处理接口。该函数终会将请求写入NVMe中的SQ队列当中,并通知控制器处理请求。

相对于SCSI设备来说,NVMe设备的驱动还是非常简单的。关于该部分的内容本文就介绍到这里,关于更多细节,还请大家自行阅读代码。

微信公众号:itworld123

分享好友

分享这个小栈给你的朋友们,一起进步吧。

Linux技术精选专区
创建时间:2020-07-08 10:30:23
Linux,全称GNU/Linux,是一套免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年次释出,它主要受到Minix和Unix思想的启发,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • dapan
    专家
戳我,来吐槽~