内容简介:Linux文件系统采用分层设计,不同层抽象出来完成不同层次的逻辑。其中的复杂的设计,可以拿两张图在不同程度上描绘:
分层结构
Linux文件系统采用分层设计,不同层抽象出来完成不同层次的逻辑。其中的复杂的设计,可以拿两张图在不同程度上描绘:
因此用户态的应用程序每一个IO请求产生的数据都会经过文件系统的不同抽象层,但是很多抽象层之间是异步交互的,这使我们理解文件系统的难度又进一步提升。当然,还可以用一个简单的抽象来表示其中每个抽象层之间的关系:
下面我们会简单分析一些场景文件IO系统调用的内核流程,让我们了解其中的内幕。
虚拟文件系统
为了连接不同文件系统的设计,内核在各种文件系统之上增加一个抽象层 虚拟文件系统(VFS) ,很多通用设计都在其中,包括一个文件在内核中如何表示、元数据 struct file 、 struct inode 等的,具体分析可以参考:《Linux虚拟文件系统》
每个文件 open 后,会得到一个 struct file 来,在用户进程中为一个 int fd 来表示,文件读写偏移等元数据存储在 struct file 中。
同时,每个文件有唯一的一个 struct inode ,文件权限、属性等存储在其中。
因此,多个 struct file 可以对应同一个 struct inode 。
pagecache
pagecache 是内核为文件创建的内存缓存,用以加速相关的文件操作。当应用程序需要读取文件中的数据时,操作系统先分配一些内存,将数据从存储设备读入到这些内存中,然后再将数据分发给应用程序;当需要往文件中写数据时,操作系统先分配内存接收用户数据,然后再将数据从内存写到磁盘上。
-
pagecache的内存在内核中是匿名的物理页(不与用户进程的逻辑地址进行映射),由struct page表示,在内核中pagecache使用LRU管理,当用户进行mmap映射文件时,内核创建对应的vma,在访问到mmap的内存区域时,触发page fault,在page fault回调中pagecache内存所属的物理页与用户进程的虚拟地址vma进行映射。 - 每个文件的
pagecache元数据存储于对应的struct inode->address_space中,因此进程之间可以共享同一个文件的pagecache,同一个文件多次open不会影响其pagecache。 - 文件的
pagecache是延时分配的,当有读写命令时,才会按需创建缓存页。 -
pagecache的脏页是单线程回写的,因此当一个文件大量写入时,写入的性能与单CPU的性能有相当的关系。
详细的分析可以参见: 《Linux内核文件Cache 机制》 、 《Linux内核延迟写机制》
块设备层
块设备层在不同版本中有不同的划分方式,但是总的来说可以分为《Linux通用块设备层》和《Linux内核IO调度层》。其中两部分可以详见链接中的讲解。
关于块设备层中的主要逻辑流程,可以参考下图:
系统调用
open
open 负责在内核生成与文件相对应的 struct file 元数据结构,并且与文件系统中该文件的 struct inode 进行关联,装载对应文件系统的操作回调函数,然后返回一个 int fd 给用户进程。后续用户对该文件的相关操作,会涉及到其相关的 struct file 、 struct inode 、 inode->i_op 、 inode->i_fop 和 inode->i_mapping->a_ops 等。
注:文件操作对应的偏移存储于 struct file 中,每个 open 的文件单独维护一份,同一个文件的读写操作共享同一个偏移。
其整个内核逻辑流程可以用下图来表示:
write
write 的写逻辑路径有好几条,最常使用的就是利用 pagecache 延迟写的这条路径,所以主要分析这个。在 write 调用的调用、返回之间,其负责分配新的 pagecache ,将数据写入 pagecache ,同时根据系统参数,判断 pagecache 中的脏数据占比来确定是否要触发回写逻辑。其详细的代码分析可以参考: 《Linux内核写文件过程》 和 《Linux内核延迟写机制》 。
其整个内核逻辑流程可以用下图来表示:
read
read 的读逻辑中包含预期 readahead 的逻辑,其可以通过与 fadvise 的配合达到文件预取的效果。这部分的代码分析可以参考: 《Linux内核读文件过程》
其整个内核逻辑流程可以用下图来表示:
fsync/fdatasync
fsync 和 fdatasync 主要逻辑流程基本相同。其通过触发对应文件的 pagecache 脏页回写,并且阻塞等待到回写逻辑完成,以达到同步数据的目的。
其整个内核逻辑流程可以用下图来表示:
mmap
用户调用 mmap 将文件映射到内存时,内核进行一系列的参数检查,然后创建对应的 vma ,然后给该 vma 绑定 vma_ops 。当用户访问到 mmap 对应的内存时,CPU会触发 page fault ,在 page fault 回调中,将申请 pagecache 中的匿名页,读取文件到其物理内存中,然后将 pagecache 中所属的物理页与用户进程的 vma 进行映射。
其整个内核逻辑流程可以用下图来表示,其中 page fault 部分比较简略,可以参考 Linux Page Fault(缺页异常) :
munmap
msync
msync 的实际实现与其手册中的描述有很大不同,其调用时, flag=MS_SYNC 等同于对 mmap 对应的文件调用 fsync ; flag=MS_ASYNC/MS_INVALIDATE 其实什么都不执行。
madvise
fadvise
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Algorithms on Strings, Trees and Sequences
Dan Gusfield / Cambridge University Press / 1997-5-28 / USD 99.99
String algorithms are a traditional area of study in computer science. In recent years their importance has grown dramatically with the huge increase of electronically stored text and of molecular seq......一起来看看 《Algorithms on Strings, Trees and Sequences》 这本书的介绍吧!