源起:
机房迁移,需要将NFS上500W级别的图片移动到另外的存储介质,本计划使用rsync,命令下去卡在"build file list"阶段,执行ls、find等命令都没有反应。最后使用了ls -f 输出了文件列表,然后使用shell脚本读取文件列表,逐个传输才解决。
这个问题引发了后续对于linux IO系统的探究,网上查了许多资料,却发现越学习越混乱,趁现在有些认识,赶紧刹车总结下,供交流学习使用,因为没有时间去扒拉kernel源码,有些观点可能不对。
只所以这部分学习下来比较乱,我觉得主要是历史上这部分变化比较大。一是网上文章大都没有说明基于哪个kernel版本,很多言之凿凿地东西都已经废弃,导致不同的文章的说法似乎还是冲突的。二是kernel在升级的过程中,有些命名或者通用叫法却得到了保留,导致理解起来更加困难(主要是page cache和disk cache部分)。
以下内容都是基于碎片的学习资料 + 个人调查理解,所以也没办法说下面的观点是基于哪个kernel版本,大致查了下,当前时间是2023-08-29,最新的kernel版本是6.5.
linux IO系统分层架构
说明:
1、虚拟文件系统(VFS)
为了屏蔽不同文件系统的差异,对上层应用提供统一的调用接口,如open()/read()/write()/close()。
同时VFS也提供一些优化策略用于加快文件访问,比如页缓存(page cache)、预读(readahead)。
2、通用块设备层
为了屏蔽底层物理存储的差异,对文件系统层提供统一的调用接口,当前kernel版本主要是submit_bio().
同时提供一些优化方案,比如IO调度策略,IO合并等。
块设备:如磁盘、SSD等此类,与键盘等字符型设备区别。详细看百度。
细节问题
文件系统
各个文件系统的实现可能会存在比较大的差异,以下以EXT4说明VFS中的一些概念。
superblock:文件系统的元数据信息,记录文件系统类型,已使用的inode数量等。
dentry: dentry就是目录,在linux中也把目录也是一种文件。
inode:文件的元数据信息,记录了文件的创建时间、权限、文件类型等,也保存了文件数据块的链接指针。通过inode里的指针可以找到具体数据。dentry也有自己的inode,inode里显示的文件类型是目录,inode指向的数据块里存放了目录下的文件列表(有文件名),格式为文件名:改文件的inode指针。