| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> 超专业解析|linux文件系统的底层架构及其工作原理 -> 正文阅读 |
|
[系统运维]超专业解析|linux文件系统的底层架构及其工作原理 |
我们先看一张图: 这张图大体上描述了 Linux 系统上,应用程序对磁盘上的文件进行读写时,从上到下经历了哪些事情。 这篇文章就以这张图为基础,介绍 Linux 在 I/O 上做了哪些事情。 文件系统什么是文件系统文件系统,本身是对存储设备上的文件,进行组织管理的机制。组织方式不同,就会形成不同的文件系统。比如常见的 Ext4、XFS、ZFS 以及网络文件系统 NFS 等等。 但是不同类型的文件系统标准和接口可能各有差异,我们在做应用开发的时候却很少关心系统调用以下的具体实现,大部分时候都是直接系统调用?open,?read,?write,?close?来实现应用程序的功能,不会再去关注我们具体用了什么文件系统(UFS、XFS、Ext4、ZFS),磁盘是什么接口(IDE、SCSI,SAS,SATA 等),磁盘是什么存储介质(HDD、SSD) 应用开发者之所以这么爽,各种复杂细节都不用管直接调接口,是因为内核为我们做了大量的有技术含量的脏活累活。开始的那张图看到 Linux 在各种不同的文件系统之上,虚拟了一个 VFS,目的就是统一各种不同文件系统的标准和接口,让开发者可以使用相同的系统调用来使用不同的文件系统。 文件系统如何工作(VFS)Linux 系统下的文件在 Linux 中一切皆文件。不仅普通的文件和目录,就连块设备、套接字、管道等,也都要通过统一的文件系统来管理。
Linux 文件系统设计了两个数据结构来管理这些不同种类的文件:
inode 和 dentryinode inode 是用来记录文件的 metadata,所谓 metadata 在 Wikipedia 上的描述是 data of data,其实指的就是文件的各种属性,比如 inode 编号、文件大小、访问权限、修改日期、数据的位置等。
inode 和文件一一对应,它跟文件内容一样,都会被持久化存储到磁盘中。所以,inode 同样占用磁盘空间,只不过相对于文件来说它大小固定且大小不算大。 dentry dentry 用来记录文件的名字、inode 指针以及与其他 dentry 的关联关系。
不同于 inode,dentry 是由内核维护的一个内存数据结构,所以通常也被叫做 dentry cache。 相关视频推荐 linux内核文件系统具体实现与内核裁剪,含30道linux内核面试题 需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享 文件是如何存储在磁盘上的这里有张图解释了文件是如何存储在磁盘上的,首先,磁盘再进行文件系统格式化的时候,会分出来 3 个区:
(其实还有 boot block,可能会包含一些 bootstrap 代码,在机器启动的时候被读到,这里忽略)其中 inode blocks 放的都是每个文件的 inode,data blocks 里放的是每个文件的内容数据。这里关注一下 superblock,它包含了整个文件系统的 metadata,具体有:
superblock 对于文件系统来说非常重要,如果 superblock 损坏了,文件系统就挂载不了了,相应的文件也没办法读写。既然 superblock 这么重要,那肯定不能只有一份,坏了就没了,它在系统中是有很多副本的,在 superblock 损坏的时候,可以使用?fsck(File System Check and repair)来恢复。回到上面的那张图,可以很清晰地看到文件的各种属性和文件的数据是如何存储在磁盘上的:
这里解释一下什么是 logical block:
ZFS这里简单介绍一个广泛应用的文件系统 ZFS,一些数据库应用也会用到 ZFS,先看一张 zfs 的层级结构图: 这是一张从底向上的图:
ZFS 的一些操作创建 zpool
除了 raidz 还支持其他方案: 创建 zfs
对 zfs 设置 quota
ZFS 特性Pool 存储上面的层级图和操作步骤可以看到 zfs 是基于 zpool 创建的,zpool 可以动态扩容意味着存储空间也可以动态扩容,而且可以创建多个文件系统,文件系统共享完整的 zpool 空间无需预分配。 事务文件系统zfs 的写操作是事务的,意味着要么就没写,要么就写成功了,不会像其他文件系统那样,应用打开了文件,写入还没保存的时候断电,导致文件为空。zfs 保证写操作事务采用的是 copy on write 的方式:
这个特性让 zfs 在断电后不需要执行 fsck 来检查磁盘中是否存在写操作失败需要恢复的情况,大大提升了应用的可用性。 ARC 缓存ZFS 中的 ARC(Adjustable Replacement Cache) 读缓存淘汰算法,是基于 IBM 的 ARP(Adaptive Replacement Cache) 演化而来。在一些文件系统中实现的标准 LRU 算法其实是有缺陷的:比如复制大文件之类的线性大量 I/O 操作,导致缓存失效率猛增(大量文件只读一次,放到内存不会被再读,坐等淘汰)。 另外,缓存可以根据时间来进行优化(LRU,最近最多使用),也可以根据频率进行优化(LFU,最近最常使用),这两种方法各有优劣,但是没办法适应所有场景。 ARC 的设计就是尝试在 LRU 和 LFU 之间找到一个平衡,根据当前的 I/O workload 来调整用 LRU 多一点还是 LFU 多一点。 ARC 定义了 4 个链表:
ARC 工作流程大致如下:
ZFS 参考资料关于 ZFS 详细介绍可以参考:
磁盘类型磁盘根据不同的分类方式,有各种不一样的类型。 磁盘的存储介质根据磁盘的存储介质可以分两类(大家都很熟悉):
磁盘的接口根据磁盘接口分类:
不同的接口,往往分配不同的设备名称。比如, IDE 设备会分配一个 hd 前缀的设备名,SCSI 和 SATA 设备会分配一个 sd 前缀的设备名。如果是多块同类型的磁盘,就会按照 a、b、c 等的字母顺序来编号。 Linux 对磁盘的管理其实在 Linux 中,磁盘实际上是作为一个块设备来管理的,也就是以块为单位读写数据,并且支持随机读写。每个块设备都会被赋予两个设备号,分别是主、次设备号。主设备号用在驱动程序中,用来区分设备类型;而次设备号则是用来给多个同类设备编号。
Generic Block Layer和 VFS 类似,为了对上层屏蔽不同块设备的差异,内核在文件系统和块设备之前抽象了一个 Generic Block Layer(通用块层),有时候一些人也会把下面的 I/O 调度层并到通用块层里表述。 这两层主要做两件事:
下图是一个完整的 I/O 栈全景图: 可以看到中间的 Block Layer 其实就是 Generic Block Layer,在图中可以看到 Block Layer 的 I/O 调度分为两类,分别表示单队列和多队列的调度:
I/O 调度老版本的内核里只支持单队列的 I/O scheduler,在 3.16 版本的内核开始支持多队列 blkmq,这里介绍几种经典的 I/O 调度策略。 单队列 I/O scheduler:
多队列 blkmq:
性能指标一般来说 I/O 性能指标有这几个:
(在做基准测试时,还会分顺序/随机、读/写进行排列组合分别去测 IOPS 和带宽) 上面的指标除了饱和度外,其他都可以在监控系统中看到。Linux 也提供了一些命令来输出不同维度的 I/O 状态:
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 15:07:00- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |