用户层read write io命令到NVMe SSD全流程

2024-04-14 07:12

本文主要是介绍用户层read write io命令到NVMe SSD全流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言

以EXT-4以及read io cmd为例,介绍从User Space -> File System -> NVMe Driver -> PCIe Controller -> NVMe Controller -> SSD Firmware(Flash Translate layer) 的基本流程

明确几个要点

  • inode number(inode号)是单纯一个整形数,一般存放在目录文件的data block里。
  • inode是struct inode对象,里面存放了跟文件相关的所有信息,结构体成员代码段1所示。
  • struct file是在打开文件时VFS分配的,fd(文件描述符)用指示struct file结构体对象,两者均属于进程。而inode不属于进程,一个文件对应一个inode。
代码段1
struct ext4_inode {  
__le16  i_mode;     /* File mode */  
__le16  i_uid;      /* Low 16 bits of Owner Uid */  
__le32  i_size_lo;  /* Size in bytes */  
__le32  i_atime;    /* Access time */  
__le32  i_ctime;    /* Inode Change time */  
__le32  i_mtime;    /* Modification time */  
__le32  i_dtime;    /* Deletion Time */  
__le16  i_gid;      /* Low 16 bits of Group Id */  
__le16  i_links_count;  /* Links count */  
__le32  i_blocks_lo;    /* Blocks count */  
__le32  i_flags;    /* File flags */  
union {  
struct {  
__le32  l_i_version;  
} linux1;  
struct {  
__u32  h_i_translator;  
} hurd1;  
struct {  
__u32  m_i_reserved1;  
} masix1;  
} osd1;             /* OS dependent 1 */  
__le32  i_block[EXT4_N_BLOCKS];/* Pointers to blocks */  
__le32  i_generation;   /* File version (for NFS) */  
__le32  i_file_acl_lo;  /* File ACL */  
__le32  i_size_high;  
__le32  i_obso_faddr;   /* Obsoleted fragment address */  
union {  
struct {  
__le16  l_i_blocks_high; /* were l_i_reserved1 */  
__le16  l_i_file_acl_high;  
__le16  l_i_uid_high;   /* these 2 fields */  
__le16  l_i_gid_high;   /* were reserved2[0] */  
__le16  l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */  
__le16  l_i_reserved;  
} linux2;  
struct {  
__le16  h_i_reserved1;  /* Obsoleted fragment number/size which are removed in ext4 */  
__u16   h_i_mode_high;  
__u16   h_i_uid_high;  
__u16   h_i_gid_high;  
__u32   h_i_author;  
} hurd2;  
struct {  
__le16  h_i_reserved1;  /* Obsoleted fragment number/size which are removed in ext4 */  
__le16  m_i_file_acl_high;  
__u32   m_i_reserved2[2];  
} masix2;  
} osd2;             /* OS dependent 2 */  
__le16  i_extra_isize;  
__le16  i_checksum_hi;  /* crc32c(uuid+inum+inode) BE */  
__le32  i_ctime_extra;  /* extra Change time      (nsec << 2 | epoch) */  
__le32  i_mtime_extra;  /* extra Modification time(nsec << 2 | epoch) */  
__le32  i_atime_extra;  /* extra Access time      (nsec << 2 | epoch) */  
__le32  i_crtime;       /* File Creation time */  
__le32  i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */  
__le32  i_version_hi;   /* high 32 bits for 64-bit version */  
__le32  i_projid;   /* Project ID */  
}; 

整体流程

假设要对根目录下的1.txt文件进行读命令

  1. 首先是挂载文件系统。文件系统挂载时,会将一部分metadata存放在内存中,其中包括Super block, Group Block信息以及"/"根目录文件的inode number
  2. 根据"/“根目录文件的inode number以及metadata可以计算出”/"文件的inode,并且通过读取inode里面的i_block找到对应的逻辑块号以及文件的长度
  3. 根据逻辑块号向NVMe SSD发起read请求,得到数据块的真实内容,这里假设该数据块已经缓存在文件系统的page cache里,下文对1.txt进行读命令时再详细分析此过程。
  4. 在data block中根据文件名(1.txt)进行索引,找到1.txt对应的inode number
  5. 根据1.txt的inode number以及metadata可以计算出"1.txt"文件的inode,并且通过读取inode里面的i_block找到对应逻辑块号和长度
  6. 将此命令传到block io layer,并根据block io layer进行调度,最后再给到NVMe驱动层。
  7. 驱动层会根据NVMe控制器的特性,将此read请求进行分割,比如一次只读取64个block,然后同时发起多个read请求
  8. 将请求写入多个SQ队列
  9. 通过PCIe Write TLP向NVMe控制器的每个sq doorbell寄存器写入新增的请求数量,通知SSD来主机端的SQ队列拿请求
  10. SSD拿到请求后解析命令,并将逻辑地址(LBA)通过FTL转化成物理块地址(PPA)
  11. 通过Flash Controller读取对应的CHIP,DIE,Plane,Block中的page。
  12. 将完成状态写入主机端的CQ队列
  13. 通过中断告诉主机端命令已经完成
  14. 主机端通过读取CQ队列获取命令完成状态

这篇关于用户层read write io命令到NVMe SSD全流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/902402

相关文章

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

java中ssh2执行多条命令的四种方法

《java中ssh2执行多条命令的四种方法》本文主要介绍了java中ssh2执行多条命令的四种方法,包括分号分隔、管道分隔、EOF块、脚本调用,可确保环境配置生效,提升操作效率,具有一定的参考价值,感... 目录1 使用分号隔开2 使用管道符号隔开3 使用写EOF的方式4 使用脚本的方式大家平时有没有遇到自

Spring Boot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)

《SpringBoot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)》本文将以一个实际案例(用户管理系统)为例,详细解析SpringBoot中Co... 目录引言:为什么学习Spring Boot分层架构?第一部分:Spring Boot的整体架构1.1

Linux命令rm如何删除名字以“-”开头的文件

《Linux命令rm如何删除名字以“-”开头的文件》Linux中,命令的解析机制非常灵活,它会根据命令的开头字符来判断是否需要执行命令选项,对于文件操作命令(如rm、ls等),系统默认会将命令开头的某... 目录先搞懂:为啥“-”开头的文件删不掉?两种超简单的删除方法(小白也能学会)方法1:用“--”分隔命

nodejs打包作为公共包使用的完整流程

《nodejs打包作为公共包使用的完整流程》在Node.js项目中,打包和部署是发布应用的关键步骤,:本文主要介绍nodejs打包作为公共包使用的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言一、前置准备二、创建与编码三、一键构建四、本地“白嫖”测试(可选)五、发布公共包六、常见踩坑提醒

k8s admin用户生成token方式

《k8sadmin用户生成token方式》用户使用Kubernetes1.28创建admin命名空间并部署,通过ClusterRoleBinding为jenkins用户授权集群级权限,生成并获取其t... 目录k8s admin用户生成token创建一个admin的命名空间查看k8s namespace 的

Ubuntu向多台主机批量传输文件的流程步骤

《Ubuntu向多台主机批量传输文件的流程步骤》:本文主要介绍在Ubuntu中批量传输文件到多台主机的方法,需确保主机互通、用户名密码统一及端口开放,通过安装sshpass工具,准备包含目标主机信... 目录Ubuntu 向多台主机批量传输文件1.安装 sshpass2.准备主机列表文件3.创建一个批处理脚

一个Java的main方法在JVM中的执行流程示例详解

《一个Java的main方法在JVM中的执行流程示例详解》main方法是Java程序的入口点,程序从这里开始执行,:本文主要介绍一个Java的main方法在JVM中执行流程的相关资料,文中通过代码... 目录第一阶段:加载 (Loading)第二阶段:链接 (Linking)第三阶段:初始化 (Initia