
导出任何设置,因为它们的队列只起到重新映射目标的作用。这些文件可以在/sys/block/xxx/queue/目录下找到。
使用RO后缀标记的文件是只读文件,RW后缀意为可读写文件。
这个文件允许关闭磁盘熵贡献。文件默认值是1(开启)。
这个文件表明设备是否支持直接访问(DAX),CPU可寻址的存储使用它绕开页缓存。
真时显示‘1’,否则显示‘0’。
如果设备报告这项信息,它显示磁盘的内部分配大小(以字节为单位)。
‘0’值表示设备不支持discard功能。
支持discard功能的设备可能包含在单个 *** 作中能够削减或解映射的内部限制字节数。
discard_max_bytes参数被设备驱动设置成在单次 *** 作中能够被丢弃的最大字节数。
发送给设备的discard请求数不允许超出这个限制。
discard_max_bytes值为0意味着设备不支持discard功能。
discard_max_hw_bytes是设备的硬件限制,而这个设置是软件限制。
当大量discard请求被发出时,一些设备表现出高延迟;
调低这一数值会使Linux发送较小的discard请求,这可能帮助降低大量discard *** 作引入的延迟。
这是设备的硬件扇区大小(以字节为单位)。
读取该文件时,它的内容显示启用(1)或禁用(0)轮询。将‘0’写入该文件将禁用设备的轮询。
写任何非0值都将启用该特性。
如果启用轮询,该参数控制执行哪种类型的轮询。默认值为-1,传统轮询。
在这种模式下,CPU将会不放弃任何时间反复地询问完成情况。
如果设置为0,将使用混合的轮询模式,内核将会尝试根据训练猜测何时IO完成。基于这一猜测,
在进入一次传统轮询循环前,内核将发出IO请求的进程置成睡眠状态一段时间。
这种模式可能比纯传统的轮询模式慢一些,但它可能更高效。
如果这个值设置大于0,在进入传统轮询前,内核将设置发出IO请求的进程睡眠这么多的微秒。
这个文件用于控制(打开/关闭)磁盘的I/O状态统计。
设备的逻辑块大小(以字节为单位)
这是单个数据传输的最大千字节数
读取这个文件时,它的内容显示显示硬件控制器能够处理的完整段的最大限制,与块层设置一致。
块层允许一个文件系统请求最大千字节数。它必须小于等于硬件允许的最大大小。
设备的段数最大值。
设备的最大段大小。
设备报告的最小首选IO大小。
它允许用户禁用涉及块层IO合并请求的查找逻辑。默认(0)启用所有合并。
当设置为1时,仅简单的one-hit合并会被尝试。当设置为2时,
不会尝试任何合并算法(包括one-hit或更复杂的树/哈希查找)。
它控制在块层可以为读或写请求分配的请求数量。注意,累计分配的数量可能是当前值的双倍,
因为它仅适用于读或写(而不是累加和)。
为了通过请求饥饿避免优先级倒置,当启用CONFIG_BLK_CGROUP,
一个请求队列为每个cgroup管理一个单独的请求池,并且这个参数适用于每一个per-block-cgroup请求池。
换句话说,如果有N个块cgroups,每一个请求队列可能有多达N个请求池,每个请求池被nr_requests单独管理。
设备报告的最佳IO大小。
设备物理块大小(以字节为单位)
文件系统在该块设备上能够预读的最大千字节数。
这个文件用于申明设备是转动类型的或是非转动类型的。
如果这个选项是‘1’,块层会将请求完成迁移到最初提交请求的CPU“组”。对于一些工作量,由于缓存效应,
这能够大幅减少CPU周期。
对于需要最大化完成处理分布(设置这个选项为‘2’)的存储配置,强制完成处理运行
在发出请求的CPU上。(绕过“组”聚合逻辑)
读取该文件时,它的内容显示设备当前使用和可用的IO调度器。当前激活的IO调度器会被放入中括号。
向该文件写入IO调度器名称会切换该块设备的控制权到新的IO调度器。注意,
如果IO调度器模块未加载到系统,写入其名称时会尝试加载它的模块。
读取这个文件时,它的内容显示设备回写缓存启用与否。对于前者,它会返回“write back”,
对于后者,它返回“write through”。写入这个文件能够改变设备的内核视图,但不能改变设备状态。
这意味着勾选设置从“write back到“write through”可能不安全,因为那样也会忽略内核刷新的缓存。
设备在单个write-same命令里能够写入的最大字节数。0值意味着设备不支持write-same命令。
如果设备注册了回写节流,那么这个文件显示目标最小读延迟。如果延迟时间超出了给定的时间窗(参见
wb_window_usec),那么回写节流会开始缩放回写。将‘0’值写入该文件会禁用该特性。
将‘-1’写入该文件会重置到默认设置。
这是blk-throttle采样数据的时间窗口(以毫秒为单位)。blk-throttle基于采样进行决策。
较低的时间意味着cgroups有更平稳的吞吐量,但是更高的CPU开销。该文件仅当启用
CONFIG_BLK_DEV_THROTTLING_LOW时存在。
Jens Axboe,2009年二月
进程读写文件之前需要 打开文件 ,得到 文件描述符 ,然后 通过文件描述符读写文件 .
内核提供了两个打开文件的系统调用 open 和 openat .
打开文件的主要步骤如下:
(1)需要 在父目录的数据中查找文件对应的目录项 , 从目录项得到索引节点的编号,然后在内存中创建索引节点的副本 .因为各种文件系统类型的物理结构不同,所以需要提供索引节点 *** 作集合的 lookup 方法和文件 *** 作集合的 open 方法.
(2)需要分配文件的一个打开实例-- file 结构体,关联到文件的索引节点.
(3)在进程的打开文件表中 分配一个文件描述符 , 把文件描述符和打开实例的映射添加到进程的打开文件表 中.
进程可通过使用系统调用 close 关闭文件.
系统调用close的执行流程如下:
(1)解除打开文件表和file实例的关联.
(2)在close_on_exec位图中清楚文件描述符对应的位.
(3)释放文件描述符,在文件描述符位图中清除文件描述符对应的位.
(4)调用函数fput释放file实例:把引用计数减1,如果引用计数是0,那么把file实例添加到链表delayed_fput_list中,然后调用延迟工作项delayed_fput_work.
延迟工作项delayed_fput_work的处理函数是flush_delayed_fput,遍历链表delayed_fput_list,针对每个file实例,调用函数__fput来加以释放.
创建不同类型的文件,需要使用不同的命令.
(1) 普通文件 :touch FILE ,这条命令本来用来更新文件的访问时间和修改时间,如果文件不存在,创建文件.
(2) 目录 :mkdir DIRECTORY .
(3) 符号链接(软链接) :ln -s TARGET LINK_NAME 或ln --symbolic TARGET LINK_NAME .
(4) 字符或块设备文件 :mknod NAME TYPE [MAJOR MINOR] .
(5) 命名管道 :mkpipe NAME .
(6) 硬连接 :命令"ln TARGET LINK_NAME ".给已经存在的文件增加新的名称,文件的索引节点有一个硬链接计数,如果文件有n个名称,那么硬链接计数是n.
创建文件需要在文件系统中 分配一个索引节点 ,然后 在父目录的数据中增加一个目录项来保存文件的名称和索引节点编号 .
删除文件的命令如下:
(1)删除任何类型文件:unlink FILE .
(2)rm FILE ,默认不删除目录,如果使用"-r""-R"或"-recursive",可以删除目录和目录的内容.
(3)删除目录:rmdir DICTIONARY .
内核提供了unlink,unlinkat用来删除文件的名称,如果文件的硬链接计数变成0,并且没有进程打开这个文件,那么删除文件.提供了rmdir删除目录.
删除文件需要从父目录的数据中删除文件对应的目录项, 把文件的索引节点的硬链接计数减1(一个文件可以有多个名称,Linux把文件名称称为硬链接),如果索引节点的硬链接计数变成0,那么释放索引节点 .因为各种文件系统的物理结构不同,所以需要提供索引节点 *** 作集合的 unlink 方法.
设置文件权限的命令如下:
(1)chmod [OPTION]... MODE[, MODE]... FILE...
mode : 权限设定字串,格式[ugoa...][[+-=][rwxX]...][,...]
其中:
(2)chmod [OPTION]... OCTAL-MODE FILE...
参数OCTAL-MODE是八进制数值.
系统调用chmod负责修改文件权限.
修改文件权限需要修改文件的索引节点的文件模式字段,文件模式字段包含文件类型和访问权限.因为各种文件系统类型的索引节点不同,所以需要提供索引节点 *** 作集合的 setattr 方法.
访问外部存储设备的速度很慢,为了避免每次读写文件时访问外部存储设备, 文件系统模块为每个文件在内存中创建一个缓存 ,因为 缓存的单位是页 ,所以称为 页缓存 .
(1) 索引节点的成员i_mapping 指向地址空间结构体(address_space).进程在打开文件的时候, 文件打开实例(file结构体)的成员f_mapping 也会指向文件的地址空间.
(2)每个文件有一个地址空间结构体 address_space ,成员 page_tree 的类型是结构体radix_tree_root:成员 gfp_mask是分配内存页的掩码,成员rnode指向基数树的根节点 .
(3)使用基数树管理页缓存,把文件的页索引映射到内存页的页描述符.
每个文件都有一个地址空间结构体address_space,用来建立数据缓存(在内存中为某种数据创建的缓存)和数据来源(即存储设备)之间的关联.结构体address_space如下:
地址空间 *** 作结合address_space_operations的主要成员如下:
页缓存的常用 *** 作函数如下:
(1)函数find_get_page根据文件的页索引在页缓存中查找内存页.
(2)函数find_or_create_page根据文件的页索引在页缓存中查找内存页,如果没有找到内存页,那么分配一个内存页,然后添加到页缓存中.
(3)函数add_to_page_cache_lru把一个内存页添加到页缓存和LRU链表中.
(4)函数delete_from_page_cache从页缓存中删除一个内存页.
进程读文件的方式有3种:
(1)调用内核提供的 读文件的系统调用 .
(2)调用glibc库封装的读文件的 标准I/O流函数 .
(3)创建基于文件的内存映射,把 文件的一个区间映射到进程的虚拟地址空间,然后直接读内存 .
第2种方式在用户空间创建了缓冲区,能减少系统调用的次数,提高性能.第3种方式可以避免系统调用,性能最高.
读文件的主要步骤如下:
(1)调用具体文件系统类型提供的文件 *** 作集合的read和read_iter方法来读文件.
(2) read或read_iter方法根据页索引在文件的页缓存中查找页,如果没有找到,那么调用具体文件系统类型提供的地址空间集合的readpage方法来从存储设备读取文件页到内存中 .
为了提高读文件的速度,从存储设备读取文件页到内存中的时候,除了读取请求的文件页,还会预读后面的文件页.如果进程按顺序读文件,预读文件页可以提高读文件的速度如果进程随机读文件,预读文件页对提高读文件的速度帮助不大.
进程写文件的方式有3种:
(1)调用内核提供的 写文件的系统调用 .
(2)调用glibc库封装的写文件的 标准I/O流函数 .
(3)创建基于文件的内存映射,把 文件的一个区间映射到进程的虚拟空间,然后直接写内存 .
第2种方式在用户空间创建了缓冲区,能够减少系统调用的次数,提高性能.第3种方式可以避免系统调用,性能最高.
写文件的主要步骤如下:
(1)调用具体文件系统类型提供的文件 *** 作集合的write或write_iter方法来写文件.
(2)write或write_iter方法调用文件的地址空间 *** 作集合的 write_begin 方法, 在页缓存查找页,如果页不存在就分配页然后把数据从用户缓冲区复制到页缓存的页中 最后调用文件的地址空间 *** 作集合的 write_end 方法.
进程写文件时,内核的文件系统模块把数据写到文件的页缓存,没有立即写回到存储设备.文件系统模块会定期把脏页写回到存储设备,进程也可以调用系统调用把脏页强制写回到存储设备.
管理员可以执行命令"sync",把内存中所有修改过的文件元数据和文件数据写回到存储设备.
内核提供了 sync , syncfs , fsync , fdatasync , sync_file_range 等系统调用用于文件写回.
把文件写回到存储设备的时机如下:
(1)周期回写.
(2)当脏页的数量达到限制的时候,强制回写.
(3)进程调用sync和syncfs等系统调用.
对于类似内存的块设备,例如NVDIMM设备,不需要把文件从存储设备复制到页缓存.DAX绕过页缓存,直接访问存储设备,对于基于文件的内存映射,直接把存储设备映射到进程的虚拟地址空间.
调用系统调用mmap创建基于文件的内存映射,把文件的一个区间映射到进程的虚拟地址空间,这会调用具体文件系统类型提供的文件 *** 作集合的mmap方法.mmap方法针对设置了标志位S_DAX的索引节点,处理方法如下:
(1)给虚拟内存区域设置标志位VM_MIXEDMAP和VM_HUGEPAGE.
(2)设置虚拟内存 *** 作集合,提供fault,huge_fault,page_mkwrite和pfn_mkwrite方法.
由 Jake Edge 发表于2018年5月18日 原文
LSFMM
在2018年的Linux存储,文件系统和内存管理峰会上,Andiry Xu发布了他正试图进入上游内核的 NOVA文件系统 。与现有的内核文件系统不同,NOVA专门针对非易失性主内存(NVMM),而不是传统的块设备(磁盘或SSD)。实际上,它根本不使用内核的Block层,而是使用直接映射到内核地址空间的持久性内存(persistent memory)。
Xu将NOVA与支持 DAX直接访问机制 的ext4和XFS文件系统版本进行了比较。有了这些,只有文件系统数据(filesystem data)绕过页面缓存元数据(metadata)仍然通过页面缓存。另外,这些文件系统对附加(append) *** 作的延迟要高得多。还有一个写入放大效应(write amplification effect)。所有这些都导致了日志记录的高开销,他说。
除此之外,NVMM上的这些文件系统还存在可扩展性问题。他在高端多核硬件上进行了一些测试,将NOVA和tmpfs与ext4和XFS的DAX模式进行比较。在他的测试中,他用RAM来模拟NVMM,因为在这一时期上很难真正获得NVMM设备。一般而言,只有tmpfs和NOVA可以合理扩展 - 其他文件系统争夺各种锁和信号量 - 尽管如此,NOVA仍有改进空间,因为只有tmpfs可以合理地按比例进行测试。
Xu表示,对于DAX文件系统来说,支持大页面是很困难的。巨大的页面要求物理地址在大页面大小的边界上对齐,并且内存物理连续,但由文件系统分配的内存不一定符合这些要求。Dave Chinner表示XFS有一个inode选项来支持大页面的使用另一位与会者表示,ext4具有类似的功能,但它只能支持2MB的大页面,而不是1GB。
Xu在2016年 NOVA论文[PDF]中 向与会者指出了更多信息,但简要介绍了NOVA的一些功能。它是为NVMM设计的日志结构文件系统。它具有只包含元数据更改的每个inode日志记录该日志指出对实际数据的更改。它使用基数树(radix tree)作为块映射,并写入复制(CoW)其文件数据。
NOVA使用轻量级的日志记录方案,该日志记录方案仅记录日志条目链接列表的头部和尾部指针。这有利于快速垃圾回收,因为当条目不再有效时就从列表中删除。除非无效条目占日志的一半以上,否则不会复制,在这种情况下,会创建一个新的日志以原子地替换旧日志元数据日志条目仅在该点复制。
他展示了一些比较DAX版本的ext4和XFS与NOVA的性能图表。通常,NOVA在他测试的大多数 filebench 工作负载上的性能要优于ext4或XFS。“Web服务器”工作负载例外,其中文件系统的执行大致相同。
Xu表示,第三个基于4.16-rc4的RFC 发布 是在3月份完成的。这篇文章收到了一些反馈意见,所以他正在研究这些项目,并将很快发布v3。所需的更改包括64位时间戳和更好的巨大页面支持。
Chinner询问了用户空间工具,特别是NOVA是否有<tt>fsck</tt>。在文件系统可以合并之前这是需要的,因为用户需要能够修复他们的文件系统。徐说,一直以来关注性能,所以没有<tt>fsck</tt>。Ted Ts'o指出NOVA还需要一个可以验证文件系统映像的工具,这将允许在xfstests上运行更多的测试。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)