NVMe离不开PCIe,NVMe SSD是PCIe的endpoint。PCIe是x86平台上一种流行的bus总线,由于其Plug and Play的特性,目前很多外设都通过PCI Bus与Host通信,甚至不少CPU的集成外设都通过PCI Bus连接,如APIC等。

NVMe SSD在PCIe接口上使用新的标准协议NVMe,由大厂Intel推出并交由nvmexpress组织推广,现在被全球大部分存储企业采纳

1.NVMe Command

NVMe Host(Server)和NVMe Controller(SSD)通过NVMe Command进行信息交互。NVMe Spec中定义了NVMe Command的格式,占用64字节。

NVMe Command分为Admin Command和IO Command两大类,前者主要是用于配置,后者用于数据传输。

NVMe Command是Host与SSD Controller交流的基本单元,应用的I/O请求也要转化成NVMe Command。

2.PCI总线

在系统启动时,BIOS会枚举整个PCI的总线,之后将扫描到的设备通过ACPI tables传给操作系统。当操作系统加载时,PCI Bus驱动则会根据此信息读取各个PCI设备的Header Config空间,从class code寄存器获得一个特征值。

class code是PCI bus用来选择哪个驱动加载设备的唯一根据。NVMe Spec定义的class code是010802h。NVMe SSD内部的Controller PCIe Header中class code都会设置成010802h。

所以,需要在驱动中指定class code为010802h,将010802h放入pci_driver nvme_driver的id_table。之后当nvme_driver注册到PCI Bus后,PCI Bus就知道这个驱动是给class code=010802h的设备使用的。nvme_driver中有一个probe函数,nvme_probe(),这个函数才是真正加载设备的处理函数。

0x010802

staticconststruct

…….

0xffffff) },

……

};

3.单独编译NVME驱动

在老版本的源码中,可以在源码路径drivers/block中,增加Makefile内容如下,进行编译:

nvme-objs := nvme-core.o nvme-scsi.o

PWD := $(shell pwd)

default:

clean:

rf *.o *.ko

然后直接即可生成nvme.ko文件。

关于Makefile可以参考如下:

KERNELVER ?= $(shell uname -r)

KERNROOT = /lib/modules/$(KERNELVER)/build

nvme:

clean:

主要就两个文件:nvme-core.c和nvme-scsi.c。

不过,最新的代码位于drivers/nvme/host中,主要是core.c和pci.c。

4.注册和初始化

我们知道首先是驱动需要注册到PCI总线。那么nvme_driver是如何注册的呢?

当驱动被加载时就会调用nvme_init(drivers/nvme/host/pci.c)函数。在这个函数中,调用了kernel的函数pci_register_driver,注册nvme_driver,其结构体如下。

staticstruct

"nvme",

};

这样PCI bus上就多了一个pci_driver nvme_driver。当读到一个设备的class code是010802h时,就会调用这个nvme_driver结构体的probe函数, 也就是说当设备和驱动匹配了之后,驱动的probe函数就会被调用,来实现驱动的加载。

Probe函数主要完成四个工作:

1.映射设备的bar空间到内存虚拟地址空间

2.设置admin queue;

3.添加nvme namespace设备;

4.添加nvme Controller,提供ioctl接口。

接着来看下nvme_driver结构体中的.probe函数nvme_probe。

staticintstructconststruct

{

intENOMEM;

struct

unsignedlong

if

sizeof(*dev), GFP_KERNEL, node);

if

returnENOMEM

1,

sizeof(struct

if

goto

if

goto

if

goto

if

goto

%s\n", dev_name(&pdev->dev));

return0;

release_pools:

unmap:

put_pci:

free:

return

}

并分配设备数据结构nvme_dev,队列nvme_queue等,结构体如下。

structnvme_dev

struct

struct

struct

struct

struct

struct

unsigned

unsigned

int

void

unsignedlong

struct

struct

bool

void

struct

struct

/* shadow doorbell buffer support: */

/* host memory buffer support: */

struct

void

};

structnvme_queue

struct

struct

struct

struct

volatilestruct

struct

};

继续说nvme_probe函数,nvme_setup_prp_pools,主要是创建dma pool,后面可以通过dma函数从dma pool中获得memory。主要是为了给4k和128k的不同IO来做优化。

nvme_init_ctrl函数会创建NVMe控制器结构体,这样在后后续probe阶段时候用初始化过的结构,其传入的操作函数集是nvme_pci_ctrl_ops。

staticconststruct

"pcie",

};

staticconststructnvme_fops

};

5.NVMe的IO

机械硬盘时代,由于其随机访问性能差,内核开发者主要放在缓存I/O、合并I/O等方面,并没有考虑多队列的设计;而Flash的出现,性能出现了戏剧性的反转,因为单个CPU每秒发出IO请求数量是有限的,所以促进了IO多队列开发。

kcalloc_node如下,可以看到队列数量是和系统中所拥有的cpu数量有关。

1,

sizeof(struct

Queue有的概念,那就是队列深度,表示其能够放多少个成员。在NVMe中,这个队列深度是由NVMe SSD决定的,存储在NVMe设备的BAR空间里。

队列用来存放NVMe Command,NVMe Command是主机与SSD控制器交流的基本单元,应用的I/O请求也要转化成NVMe Command。

不过需要注意的是,就算有很多CPU发送请求,但是块层并不能保证都能处理完,将来可能要绕过IO栈的块层,不然瓶颈就是操作系统本身了。

当前Linux内核提供了blk_queue_make_request函数,调用这个函数注册自定义的队列处理方法,可以绕过io调度和io队列,从而缩短io延时。Block层收到上层发送的IO请求,就会选择该方法处理,如下图:

从图中可 以看出NVMe SSD I/O路径并不经传统的块层。

6.DMA

PCIe有个寄存器位Bus Master Enable,这个bit置1后,PCIe设备就可以向Host发送DMA Read Memory和DMA Write Memory请求。

当Host的driver需要跟PCIe设备传输数据的时候,只需要告诉PCIe设备存放数据的地址就可以。

NVMe Command占用64个字节,另外其PCIe BAR空间被映射到虚拟内存空间(其中包括用来通知NVMe SSD Controller读取Command的Doorbell寄存器)。

NVMe数据传输都是通过NVMe Command,而NVMe Command则存放在NVMe Queue中,其配置如下图。

其中队列中有Submission Queue,Completion Queue两个。

7.参考

linux内核nvme驱动程序,Linux中nvme驱动详解相关推荐

  1. Linux内核学习笔记(6)-- 进程优先级详解(prio、static_prio、normal_prio、rt_priority)...

    Linux 中采用了两种不同的优先级范围,一种是 nice 值,一种是实时优先级.在上一篇粗略的说了一下 nice 值和实时优先级,仍有不少疑问,本文来详细说明一下进程优先级.linux 内核版本为 ...

  2. linux 系统调用 优先级,Linux内核学习笔记(6)-- 进程优先级详解(prio、static_prio、normal_prio、rt_priority)...

    Linux 中采用了两种不同的优先级范围,一种是 nice 值,一种是实时优先级.在上一篇粗略的说了一下 nice 值和实时优先级,仍有不少疑问,本文来详细说明一下进程优先级.linux 内核版本为 ...

  3. linux内核epub,Android底层开发技术实战详解——内核、移植和驱动(第2版)[EPUB][MOBI][AZW3][42.33MB]...

    内容简介 本书从底层原理开始讲起,结合真实的案例向读者详细介绍了Android内核.移植和驱动开发的整个流程.全书分为21章,依次讲解驱动移植的必要性, Goldfish.OMAP内核和驱动解析,显示 ...

  4. linux内核(4.17.10)配置项详解(x86)

    64-bit kernel--支持64位 General setup--通用设置 Cross-compiler tool prefix--交叉编译工具前缀 Local version-append t ...

  5. Linux MTD架构下的nand flash驱动详解

    转载自:http://blog.csdn.net/wang_zheng_kai/article/details/18988521 有了前面的基础(Nandflash详解:https://blog.cs ...

  6. 【学习笔记】编译Linux内核(下)---KConfig、Makefile详解以及ARM平台Linux内核的编译

    本文主要介绍Linxu2.6的内核配置系统. 如果你浏览一下源代码目录,就可以发现源码目录及其子目录中有很多的KConfig文件和Makefile文件.这些文件什么作用呢?正是这些文件组成了Linux ...

  7. 编译arm linux内核,编译Linux内核(下)---KConfig、Makefile详解以及ARM平台Linux内核的编译...

    转载自:http://blog.csdn.net/newthinker_wei/article/details/8022696 本文主要介绍Linxu2.6的内核配置系统. 如果你浏览一下源代码目录, ...

  8. linux内核 块驱动程序,linux – 为什么内核使用默认的块驱动程序而不是我的驱动程序代码?...

    我写了一个块驱动程序,它创建了一个虚拟块设备(sbd0).我为该块设备注册了所有设备操作:(请参阅2.6.32内核源代码中的include / linux / blkdev.h) static str ...

  9. 16.Linux-LCD驱动(详解)

    在上一节LCD层次分析中,得出写个LCD驱动入口函数,需要以下4步: 1) 分配一个fb_info结构体: framebuffer_alloc(); 2) 设置fb_info 3) 设置硬件相关的操作 ...

  10. Linux内核 LCD 驱动程序框架

    Linux 内核 LCD 驱动程序框架 1. framebuffer 简介 1.1 什么是 framebuffer 1.2 framebuffer的作用 2. framebuffer 驱动的框架 3. ...

最新文章

  1. C#获得枚举类型的长度
  2. 先理解Mask R-CNN的工作原理,然后构建颜色填充器应用
  3. C#字节数组与值类型变量的互相转换,以及注意事项
  4. plsql查询中补入空行--做报表分页挺有用
  5. juc线程池原理(六):jdk线程池中的设计模式
  6. 图像分块matlab程序,图像分块 matlab程序
  7. socket编程(一)
  8. McBSP初始化以及和EDMA的结合使用(C64X DSP)
  9. 安卓ViewFlipper跑马灯效果
  10. 计算机领域有哪些常见的比赛
  11. HDU 2079 选课时间(题目已修改,注意读题)(母函数)
  12. 三维绕任意轴旋转矩阵
  13. 姿态估计1-03:FSA-Net(头部姿态估算)-白话给你讲论文-翻译无死角(1)
  14. 15.9 文本查询程序再探(继承)
  15. 二维码第三方支付介绍
  16. ffmpeg delogo滤镜去除图片水印
  17. 自我觉知和自我知觉(self-perception)
  18. 2020上海全国计算机一级考试时间,2020全国等级计算机考试时间(全国计算机一级报名时间)...
  19. 写给成为高手之路上的朋友们
  20. 数据安全--12--隐私保护浅析

热门文章

  1. Java并发包实际应用_Java并发包之核心AQS
  2. 机器视觉软件工程师的生活是怎样的?
  3. 【源码好又多】开源在线教育系统
  4. Coursera学科分类爬虫实例介绍
  5. SQL 数据库基本操作
  6. 史上最全SQL基础知识总结(理论+举例)
  7. 数据库入门(SQL SEVER)之SQL语句删除单行数据,所有行数据,表和数据库
  8. 微信小程序学习资料[转]
  9. 如果计算机正执行屏幕保护程序 当用户,计算机一级考试参考试题(含答案)讲节一.doc...
  10. c语言程序设计第4版pdf荣政_C语言程序设计 PDF 第4版