最近在做磁盘性能优化,需要结合文件系统原理去思考优化方向,因此借此机会进一步加深了对文件系统的认识。在看这篇文章之前,建议先看下前面一篇关于磁盘工作原理的解读。下面简单总结一些要点分享出来:

一、文件系统层次分析

由上而下主要分为用户层、VFS层、文件系统层、磁盘驱动层、磁盘物理层

用户层:最上面用户层就是我们日常使用的各种程序,需要的接口主要是文件的创建、删除、打开、关闭、写、读等。

VFS层:我们知道Linux分为用户态和内核态,用户态请求硬件资源需要调用System Call通过内核态去实现。用户的这些文件相关操作都有对应的System Call函数接口,接口调用 VFS对应的函数。

文件系统层:不同的文件系统实现了VFS的这些函数,通过指针注册到VFS里面。所以,用户的操作通过VFS转到各种文件系统。文件系统把文件读写命令转化为对磁盘LBA的操作,起了一个翻译和磁盘管理的作用。 缓存层:文件系统底下有缓存,Page Cache,加速性能。对磁盘LBA的读写数据缓存到这里。 块设备层:块设备接口Block Device是用来访问磁盘LBA的层级,读写命令组合之后插入到命令队列,磁盘的驱动从队列读命令执行。Linux设计了电梯算法等对很多LBA的读写进行优化排序,尽量把连续地址放在一起。

磁盘驱动层:磁盘的驱动程序把对LBA的读写命令转化为各自的协议,比如变成ATA命令,SCSI命令,或者是自己硬件可以识别的自定义命令,发送给磁盘控制器。Host Based SSD甚至在块设备层和磁盘驱动层实现了FTL,变成对Flash芯片的操作。

磁盘物理层:读写物理数据到磁盘介质。

二、文件系统结构与工作原理(主要以ext4为例)

我们都知道,windows文件系统主要有fat、ntfs等,而linux文件系统则种类多的很,主要有VFS做了一个软件抽象层,向上提供文件操作接口,向下提供标准接口供不同文件系统对接,下面主要就以EXT4文件系统为例,讲解下文件系统结构与工作原理:

上面两个图大体呈现了ext4文件系统的结构,从中也相信能够初步的领悟到文件系统读写的逻辑过程。下面对上图里边的构成元素做个简单的讲解:

引导块:为磁盘分区的第一个块,记录文件系统分区的一些信息,,引导加载当前分区的程序和数据被保存在这个块中。一般占用2kB,

超级块:

超级块用于存储文件系统全局的配置参数(譬如:块大小,总的块数和inode数)和动态信息(譬如:当前空闲块数和inode数),其处于文件系统开始位置的1k处,所占大小为1k。为了系统的健壮性,最初每个块组都有超级块和组描述符表(以下将用GDT)的一个拷贝,但是当文件系统很大时,这样浪费了很多块(尤其是GDT占用的块多),后来采用了一种稀疏的方式来存储这些拷贝,只有块组号是3, 5 ,7的幂的块组(譬如说1,3,5,7,9,25,49…)才备份这个拷贝。通常情况下,只有主拷贝(第0块块组)的超级块信息被文件系统使用,其它拷贝只有在主拷贝被破坏的情况下才使用。

块组描述符:

GDT用于存储块组描述符,其占用一个或者多个数据块,具体取决于文件系统的大小。它主要包含块位图,inode位图和inode表位置,当前空闲块数,inode数以及使用的目录数(用于平衡各个块组目录数),具体定义可以参见ext3_fs.h文件中struct ext3_group_desc。每个块组都对应这样一个描述符,目前该结构占用32个字节,因此对于块大小为4k的文件系统来说,每个块可以存储128个块组描述符。由于GDT对于定位文件系统的元数据非常重要,因此和超级块一样,也对其进行了备份。GDT在每个块组(如果有备份)中内容都是一样的,其所占块数也是相同的。从上面的介绍可以看出块组中的元数据譬如块位图,inode位图,inode表其位置不是固定的,当然默认情况下,文件系统在创建时其位置在每个块组中都是一样的,如图2所示(假设按照稀疏方式存储,且n不是3,5,7的幂)

块组:

每个块组包含一个块位图块,一个 inode 位图块,一个或多个块用于描述 inode 表和用于存储文件数据的数据块,除此之外,还有可能包含超级块和所有块组描述符表(取决于块组号和文件系统创建时使用的参数)。下面将对这些元数据作一些简要介绍。

块位图:

块位图用于描述该块组所管理的块的分配状态。如果某个块对应的位未置位,那么代表该块未分配,可以用于存储数据;否则,代表该块已经用于存储数据或者该块不能够使用(譬如该块物理上不存在)。由于块位图仅占一个块,因此这也就决定了块组的大小。

Inode位图:

Inode位图用于描述该块组所管理的inode的分配状态。我们知道inode是用于描述文件的元数据,每个inode对应文件系统中唯一的一个号,如果inode位图中相应位置位,那么代表该inode已经分配出去;否则可以使用。由于其仅占用一个块,因此这也限制了一个块组中所能够使用的最大inode数量。

Inode表:

Inode表用于存储inode信息。它占用一个或多个块(为了有效的利用空间,多个inode存储在一个块中),其大小取决于文件系统创建时的参数,由于inode位图的限制,决定了其最大所占用的空间。

以上这几个构成元素所处的磁盘块成为文件系统的元数据块,剩余的部分则用来存储真正的文件内容,称为数据块,而数据块其实也包含数据和目录。

了解了文件系统的结构后,接下来我们来看看操作系统是如何读取一个文件的:

大体过程如下:

1、根据文件所在目录的inode信息,找到目录文件对应数据块

2、根据文件名从数据块中找到对应的inode节点信息

3、从文件inode节点信息中找到文件内容所在数据块块号

4、读取数据块内容

到这里,相信很多人会有一个疑问,我们知道一个文件只有一个Inode节点来存放它的属性信息,那么你可能会想如果一个大文件,那它的block一定是多个的,且可能不连续的,那么inode怎么来表示呢,下面的图告诉你答案:

也就是说,如果文件内容太大,对应数据块数量过多,inode节点本身提供的存储空间不够,会使用其他的间接数据块来存储数据块位置信息,最多可以有三级寻址结构。

到这里,应该都已经非常清楚文件读取的过程了,那么下面再抛出两个疑问:

1、文件的拷贝、剪切的底层过程是怎样的?

2、软连接和硬连接分别是如何实现的?

下面来结合stat命令动手操作一下,便知真相:

1)拷贝文件:创建一个新的inode节点,并且拷贝数据块内容

2)剪切文件:同个分区里边mv,inode节点不变,只是更新目录文件对应数据块里边的文件名和inode对应关系;跨分区mv,则跟拷贝一个道理,需要创建新的inode,因为inode节点不同分区是不能共享的。

3)软连接:创建软连接会创建一个新的inode节点,其对应数据块内容存储所链接的文件名信息,这样原文件即便删除了,重新建立一个同名的文件,软连接依然能够生效。

4、硬链接:创建硬链接,并不会新建inode节点,只是links加1,还有再目录文件对应数据块上增加一条文件名和inode对应关系记录;只有将硬链接和原文件都删除之后,文件才会真正删除,即links为0才真正删除。

关于文件系统的就讲这么多,下篇会讲解linux内核提供的一个资源管控机制cgroup,分析其原理及使用过程。

ext4文件系统bug:
http://www.phoronix.com/scan.php?page=news_item&px=MTIxNDQ

ext4文件系统描述:
http://blog.csdn.net/liangchen0322/article/details/50365685
http://blog.csdn.net/fybon/article/details/26243971
hexdump查看磁盘结构信息:
http://www.cnblogs.com/jiangcsu/p/5737659.html

linux文件系统详解的更多相关文章

  1. [转帖]Linux文件系统详解

    Linux文件系统详解 https://www.cnblogs.com/alantu2018/p/8461749.html 贼复杂.. 从操作系统的角度详解Linux文件系统层次.文件系统分类.文件系 ...

  2. Linux 文件系统详解

    作者: Paul Brown 译者: LCTT amwps290 这篇教程将帮你快速了解 Linux 文件系统. 早在 1996 年,在真正理解文件系统的结构之前,我就学会了如何在我崭新的 Linux ...

  3. Linux学习笔记之Linux文件系统详解

    0x00 机械硬盘 机械磁盘由磁头(head).磁道(track).柱面(cylinder).扇区(sector)和盘片(platter)组成.其中,磁头悬浮在盘片上,并且每张盘片上下各有一个磁头:每 ...

  4. (十三)linux文件系统详解(基于ext2文件系统)【转】

    本文转载自:https://blog.csdn.net/FadeFarAway/article/details/53959639 我们知道,一个磁盘可以划分成多个分区,每个分区必须先用格式化工具(例如 ...

  5. Linux 系统结构详解

    Linux 系统结构详解 Linux系统一般有4个主要部分: 内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用系统 ...

  6. Linux init详解(转)

    Linux init详解 一.什么是INIT: init是Linux系统操作中不可缺少的程序之一. 所谓的init进程,它是一个由内核启动的用户级进程. 内核自行启动(已经被载入内存,开始运行,并已初 ...

  7. Linux内存详解

    --Linux内存详解 -----------------2014/05/24 Linux的内存上表现的不像windows那么直观,本文准备详细的介绍一下Linux的内存. 请看这下有linux命令f ...

  8. Docker 基础技术之 Linux cgroups 详解

    PS:欢迎大家关注我的公众号:aCloudDeveloper,专注技术分享,努力打造干货分享平台,二维码在文末可以扫,谢谢大家. 推荐大家到公众号阅读,那里阅读体验更好,也沉淀了很多篇干货. 前面两篇 ...

  9. Linux 目录详解 树状目录结构图

    1.树状目录结构图 2./目录 目录 描述 / 第一层次结构的根.整个文件系统层次结构的根目录. /bin/ 需要在单用户模式可用的必要命令(可执行文件):面向所有用户,例如:cat.ls.cp,和/ ...

随机推荐

  1. python3 入门基础

    1.查看python版本 python -V 2.指定python文件的编码格式 # -*- coding: utf-8 -*- 3.变量命名以字母和下划线(_)开始 _num num 4.注释 # ...

  2. 实现微信浏览器自动播放MP3音乐

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. swift 中使用OC第三方库(以AFNetworking为例)

    首先呢  把你需要的第三方库导入到你的项目中来  具体怎么导入 这不是这篇的重点  看上一篇 废话不多  直接上 (1)在项目中直接建一个 oc 的控制器  然后xcode会提醒你  要不要建造桥接文 ...

  4. swift 使用pod管理

    在oc 中使用pod 管理第三方库还是很方便的 今天来在swift中使用pod 来管理第三方库 其实还是很简单的 和oc 区别不大  下面来说说我遇到的一些问题及解决方法 当然使用pod 你要先安装p ...

  5. Java程序性能优化读书笔记(一):Java性能调优概述

    程序性能的主要表现点: 执行速度:程序的反映是否迅速,响应时间是否足够短 内存分配:内存分配是否合理,是否过多地消耗内存或者存在内存泄漏 启动时间:程序从运行到可以正常处理业务需要花费多少时间 负载承 ...

  6. 未来手机Alo即将问世!全息投影手机的新高峰!全息3d 网

    文章来源:网络         编辑:大熊 [摘要]全息投影手机很早就开始炒,网络上的概念机也是丛出不穷,那么这款出自法国的概念机又是多么的奇葩?全息 3d 网带你一探究竟. 据外媒报道,在不久将来语 ...

  7. windows下搭建GO开发环境

    1. Go下载 由于某些原因golang.org不能访问,可以使用下面的镜像地址进行下 http://fossies.org/windows/misc/ 我的环境是win8 64位,所以选择go1.7 ...

  8. 列存储段消除(ColumnStore Segment Elimination)

    列存储索引是好的!对于数据仓库和报表工作量,它们是真正的性能加速器.与聚集列存储结合,你会在常规行存储索引(聚集索引,非聚集索引)上获得巨大的压缩好处.而且创建聚集列存储索引非常简单: CREATE ...

  9. C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)

    译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 ...

  10. 集成支付宝-iOS

    前言 坑坑坑,把踩过的坑都要记下来!! 正文 1.支付宝的demo和文档都好难找啊@_@,像我这个记忆不太好的,第二次都找不到!!为了方便大家,还是直接给大家网址吧,(不要太感谢我喔~)https:/ ...