理解ext文件系统

@(0001学习博客)

注意:本文参考骏马金龙的博客,详情请移步浏览

一、一些常见的文件系统

  • Linux的文件系统: ext2(无日志功能), ext3, ext4, xfs, reiserfs, btrfs
  • 光盘:iso9660
  • 交换文件系统:swap (虚拟内存)
  • 网络文件系统:nfs, cifs
  • 集群文件系统:gfs2, ocfs2
  • 内核级分布式文件系统:ceph
  • windows的文件系统:vfat, ntfs
  • 伪文件系统:proc, sysfs, tmpfs, hugepagefs
  • Unix的文件系统:UFS, FFS, JFS
  • 用户空间的分布式文件系统:mogilefs, moosefs, glusterfs

二、文件系统的组成

1. block:块

Linux文件系统中使用“block”块为读写单元,块的大小一般为1024bytes(1k)或2048bytes(2k)或4096bytes(4k)。比如需要读一个或多个块时,文件系统的IO管理器通知磁盘控制器要读取哪些块的数据,硬盘控制器将这些块按扇区读取出来,再通过硬盘控制器将这些扇区数据重组返回给计算机。但是其缺点就是会照成空间浪费,比如一个只有96字节的文件也要完整的占有一个块,那么剩余的空间就会造成浪费。

2. inode(index node,索引节点)、inode表

inode的作用主要是高效、有序的查找文件,而文件存储于数量不一的block中。

inode中存储了inode号、文件类型、权限、文件所有者、大小、时间戳等元数据信息,还存储了指向属于该文件block的指针,这样读取inode就可以找到属于该文件的block,进而读取这些block并获得该文件的数据。可以将inode同类理解为目录。

使用stat /FILE命令可以查看文件的元数据:

[root@CentOS7 ~]#stat /etc/passwd
File: ‘/etc/passwd’
Size: 2400 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 68307519 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:passwd_file_t:s0
Access: 2018-11-23 08:05:31.449000177 +0800
Modify: 2018-11-20 18:53:20.214867983 +0800
Change: 2018-11-20 18:53:20.215867983 +0800
Birth: -

这里再提出一个概念:inode表。

假如每个inode128字节,一个4K的block就可以存放32个inode,再将这些存放inode的块组合起来就行成了inode table(inode表)。

举个例子,每一个家庭都要向派出所登记户口信息,通过户口本可以知道家庭住址,而每个镇或街道的派出所将本镇或本街道的所有户口整合在一起,要查找某一户地址时,在派出所就能快速查找到。inode table就是这里的派出所。

3. bmap(bitmap index)、imap(inode map)位图索引

3.1 bmap

在向硬盘存储数据时,文件系统需要知道哪些块是空闲的,哪些块是已经占用了的,bmap的作用就是总览硬盘中哪些block被占用,哪些是空闲的,这样可以高效写入数据。

位图只使用0和1标识对应block是空闲还是被占用,0和1在位图中的位置和block的位置一一对应,第一位标识第一个块,第二个位标识第二个块,依次下去直到标记完所有的block。比如:对于一个block大小为1KB、容量为1G的文件系统而言,block数量有10241024个,所以在bmap位图中使用10241024个位共1024*1024/8=131072字节=128K,即1G的文件只需要128个block做位图就能完成一一对应。通过扫描这100多个block就能知道哪些block是空闲的,速度提高了非常多。

注意:bmap优化针对的是写入优化,对读取优化使用的是inode。

3.2 imap

imap的作用同理bmap,也是为了让系统迅速了解哪些inode在使用,哪些处于空闲状态

4.块组

为解决bmap、inode table和imap太大的问题,比如100G文件就需要128k*100=12.5M的bmap空间,系统扫描这个空间也是蛮费时间,因此我们将占用的block分成block groups(块组)。

注意:在物理层面上的划分是将磁盘按柱面划分为多个分区,即多个文件系统;在逻辑层面上的划分是将文件系统划分成块组。每个文件系统包含多个块组,每个块组包含多个元数据区和数据区:元数据区就是存储bmap、inode table、imap等的数据;数据区就是存储文件数据的区域。注意块组是逻辑层面的概念,所以并不会真的在磁盘上按柱面、按扇区、按磁道等概念进行划分。

下面介绍如何划分块组:

它只需确定一个数据——每个block的大小,再根据bmap至多只能占用一个完整的block的标准就能计算出块组如何划分。如果文件系统非常小,所有的bmap总共都不能占用完一个block,那么也只能空闲bmap的block了。

(注意:每个block的大小在创建文件系统时可以人为指定,不指定也有默认值。)

假如现在block的大小是1KB,一个bmap完整占用一个block能标识1024*8= 8192个block(当然这8192个block是数据区和元数据区共8192个,因为元数据区分配的block也需要通过bmap来标识)。每个block是1K,每个块组是8192K即8M,创建1G的文件系统需要划分1024/8=128个块组,如果是1.1G的文件系统呢?128+12.8=128+13=141个块组。

可以使用dumpe2fs /dev/sda1 查看相关信息:

ext4文件系统的信息:

[root@CentOS6 ~]#dumpe2fs /dev/sda1
dumpe2fs 1.41.12 (17-May-2010)
Filesystem volume name: <none>
Last mounted on: /boot # 挂载点
Filesystem UUID: db5da648-a6e9-41e2-b9bb-1ec771e61499
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl # 开通acl功能
Filesystem state: clean
Errors behavior: Continue #错误时继续进行
Filesystem OS type: Linux
Inode count: 65536 # inode号数量
Block count: 262144 # block数量
Reserved block count: 13107 # 保存的block数量
Free blocks: 239740 # 空闲的block数量
Free inodes: 65497 # 空闲的inode数量
First block: 0 # 第一个block号
Block size: 4096 # block大小4k
Fragment size: 4096
Reserved GDT blocks: 63 # 保留的GDT block数量
Blocks per group: 32768 # 每个块组的block数量
Fragments per group: 32768
Inodes per group: 8192 # 每个块组的inode数量
Inode blocks per group: 512 # 每个块组inode占用的块数量,即inode表大小,512*4k
Flex block group size: 16 #
Filesystem created: Tue Oct 23 18:35:07 2018
Last mount time: Fri Nov 23 02:43:10 2018
Last write time: Fri Nov 23 02:43:10 2018
Mount count: 31
Maximum mount count: -1
Last checked: Tue Oct 23 18:35:07 2018
Check interval: 0 (<none>)
Lifetime writes: 88 MB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256 # inode大小
Required extra isize: 28
Desired extra isize: 28
Journal inode: 8 # 日志文件的inode数
Default directory hash: half_md4
Directory Hash Seed: 50ef58d8-3fa1-473a-84d0-2e0a5156c604
Journal backup: inode blocks
Journal features: (none)
Journal size: 32M
Journal length: 8192
Journal sequence: 0x0000002b
Journal start: 0

可见:该分区中共有262144个block,每个块大小4k,所以该分区容量为1G,每个块组包含32768个块,一个分了8个块组。

5.块组里的其他block

5.1 Boot Block 引导块

Boot Block也称为boot sector。它位于分区上的第一个块,占用1024字节,并非所有分区都有这个boot sector,只有装了操作系统的主分区和装了操作系统的逻辑分区才有。里面存放的也是boot loader,这段boot loader称为VBR(主分区装操作系统时)或EBR(扩展分区装操作系统时),这里的Boot loader和mbr上的boot loader是存在交错关系的。开机启动的时候,首先加载mbr中的bootloader,然后定位到操作系统所在分区的boot serctor上加载此处的boot loader。

5.2 Superblock(超级块)

超级块(superblock)用于存储文件系统本身的属性信息:如各种时间戳、block总数量和空闲数量、inode总数量和空闲数量、当前文件系统是否正常、什么时候需要自检等等。

超级块占用1024字节,也需要一个block,所以这个块称为superblock,他的块号可能为0,也可能为1。如果block大小为1K,则引导块正好占用一个block,这个block号为0,所以superblock的号为1;如果block大小大于1K,则引导块和超级块同置在一个block中,这个block号为0。总之superblock的起止位置是第二个1024(1024-2047)字节。

df 命令读取的就是每个文件系统的超级块内的信息,所以其速度非常快。相反,用du命令查看一个较大目录的已用空间就非常慢,因为不可避免地要遍历整个目录的所有文件。

[root@CentOS6 ~]#df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda2 50264772 4376228 43328544 10% /
tmpfs 1019176 76 1019100 1% /dev/shm
/dev/sda1 999320 40360 906532 5% /boot
/dev/sda3 30106576 45032 28525544 1% /data
/dev/sr0 3878870 3878870 0 100% /media/CentOS_6.9_Final

superblock对于文件系统而言是至关重要的,超级块丢失或损坏必将导致文件系统的损坏,所以超级块的信息会在块组上有备份。

dumpe2fs -h /dev/sda1获取超级块信息(dumpe2fs /dev/sda1 略同)

[root@CentOS6 ~]#dumpe2fs -h /dev/sda1

dumpe2fs 1.41.12 (17-May-2010)
Filesystem volume name: <none>
Last mounted on: /boot
Filesystem UUID: db5da648-a6e9-41e2-b9bb-1ec771e61499
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 65536
Block count: 262144
Reserved block count: 13107
Free blocks: 239740
Free inodes: 65497
First block: 0
Block size: 4096
Fragment size: 4096
Reserved GDT blocks: 63
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 8192
Inode blocks per group: 512
Flex block group size: 16
Filesystem created: Tue Oct 23 18:35:07 2018
Last mount time: Fri Nov 23 02:43:10 2018
Last write time: Fri Nov 23 02:43:10 2018
Mount count: 31
Maximum mount count: -1
Last checked: Tue Oct 23 18:35:07 2018
Check interval: 0 (<none>)
Lifetime writes: 88 MB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 28
Desired extra isize: 28
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: 50ef58d8-3fa1-473a-84d0-2e0a5156c604
Journal backup: inode blocks
Journal features: (none)
Journal size: 32M
Journal length: 8192
Journal sequence: 0x0000002b
Journal start: 0

5.3 GDT(块组描述符表)

记录每个块组的信息和属性等元数据,大小为32个字节。

虽然每个块组都需要块组描述符来记录块组的信息和属性元数据,但是不是每个块组中都存放了块组描述符。ext文件系统的存储方式是:将它们组成一个GDT,并将该GDT存放于某些块组中,存放GDT的块组和存放superblock和备份superblock的块相同,也就是说它们是同时出现在某一个块组中的。读取时也总是读取Group0中的块组描述符表信息。

假如block大小为4KB的文件系统划分了143个块组,每个块组描述符32字节,那么GDT就需要143*32=4576字节即两个block来存放。这两个GDT block中记录了所有块组的块组信息,且存放GDT的块组中的GDT都是完全相同的。

dumpe2fs /dev/sda1命令后面的显示信息就是GDT

5.4 Reserved GDT(保留GDT)

保留GDT用于以后扩容文件系统使用,防止扩容后块组太多,使得块组描述符超出当前存储GDT的blocks。保留GDT和GDT总是同时出现,当然也就和superblock同时出现了。

完整的文件系统结构图

6.Data block

数据所占用的block由文件对应inode记录中的block指针找到,不同的文件类型,数据block中存储的内容是不一样的。以下是Linux中不同类型文件的存储方式:

  • 对于常规文件,文件的数据正常存储在数据块中。
  • 对于目录,该目录下的所有文件和一级子目录的目录名存储在数据块中。
    • 文件名不是存储在其自身的inode中,而是存储在其所在目录的data block中。
  • 对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存。
  • 设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中。

6.1 目录文件

对于目录文件,其inode记录中存储的是目录的inode号、目录的属性元数据和目录文件的block指针,这里面没有存储目录自身文件名的信息。

目录的data block中并没有直接存储目录中文件的inode号,它存储的是指向inode table中对应文件inode号的指针。

* block指针:每个inode号指向的block

* inode指针:目录文件其inode指向inode表

比如:对于没有执行权限的目录文件,我们ll /FILE/TO/并不能读取到该目录下的文件信息,只能读到目录本身的信息。

所以,目录文件的读权限(r)和写权限(w),都是针对目录文件的数据块本身。由于目录文件内只有文件名、文件类型和inode指针,所以如果只有读权限,只能获取文件名和文件类型信息,无法获取其他信息,尽管目录的data block中也记录着文件的inode指针,但定位指针是需要x权限的,因为其它信息都储存在文件自身对应的inode中,而要读取文件inode信息需要有目录文件的执行权限通过inode指针定位到文件对应的inode记录上。

补充:硬链接与软链接的区别:

  • 硬链接:指向同一个inode的多个文件路径,但需在同一个分区中

    • 目录不支持硬链接;
    • 硬链接不能跨文件系统(跨分区);
    • 创建硬链接会增加inode引用计数
    • 修改符号链接文件的权限,变动的是源文件的权限
    • 无论修改硬链接中的哪个文件,全部的文件都会跟着改动权限
    • ln file1 file2
  • 软链接:指向一个文件路径的另一个文件路径

    • 符号链接与文件是两人个各自独立的文件,各有自己的inode;对原文件创建符号链接不会增加引用计数;
    • 支持对目录创建符号链接,可以跨文件系统;
    • 删除符号链接文件不影响原文件;但删除原文件,符号指定的路径即不存在,此时会变成无效链接;
    • 符号链接文件的大小是其指定的文件的路径字符串的字节数
    • ln -s file1 file2

三、示例解读:cat /var/log/messages

  1. 找到根文件系统的块组描述符表所在的blocks,读取GDT(已在内存中)找到inode table的block号。
  1. 在inode table的block中定位到根"/"的inode,找出"/"指向的data block。
  2. 在"/"的datablock中记录了var目录名和指向var目录文件inode的指针,并找到该inode记录,inode记录中存储了指向var的block指针,所以也就找到了var目录文件的data block。
  3. 在var的data block中记录了log目录名和其inode指针,通过该指针定位到该inode所在的块组及所在的inode table,并根据该inode记录找到log的data block。
  4. 在log目录文件的data block中记录了messages文件名和对应的inode指针,通过该指针定位到该inode所在的块组及所在的inode table,并根据该inode记录找到messages的data block。
  5. 最后读取messages对应的datablock。

简言之:找到GDT-->找到"/"的inode-->找到/的数据块读取var的inode-->找到var的数据块读取log的inode-->找到log的数据块读取messages的inode-->找到messages的数据块并读取它们。

理解ext文件系统的更多相关文章

  1. 第4章 ext文件系统机制

    本文目录: 4.1 文件系统的组成部分 4.2 文件系统的完整结构 4.3 Data Block 4.4 inode基础知识 4.5 inode深入 4.6 单文件系统中文件操作的原理 4.7 多文件 ...

  2. 第4章 ext文件系统机制原理剖析

    将磁盘进行分区,分区是将磁盘按柱面进行物理上的划分.划分好分区后还要进行格式化,然后再挂载才能使用(不考虑其他方法).格式化分区的过程其实就是创建文件系统. 文件系统的类型有很多种,如CentOS 5 ...

  3. ext文件系统机制原理剖析

    本文转载自ext文件系统机制原理剖析 导语 将磁盘进行分区,分区是将磁盘按柱面进行物理上的划分.划分好分区后还要进行格式化,然后再挂载才能使用(不考虑其他方法).格式化分区的过程其实就是创建文件系统. ...

  4. 转 ext文件系统及块组

    一.文件系统概述 1. 引导块 前文中介绍过磁盘需要进行分区和格式化,才能创建文件系统并使用,那么一块已经被各式化了分区其结构是什么样的呢?分区是按照柱面来划分的,而柱面包含的是磁道,磁道上包含的是扇 ...

  5. Linux EXT 文件系统 详解

    上几章我们讲到了Linux启动的一些问题,接下来我们来看一下硬盘分割和EXT格式文件系统的问题.前面提到了分区表的问题,分区表位于MBR, 占用64个字节.所谓的硬盘分区也就是对硬盘进行规划,填写分区 ...

  6. Linux学习之CentOS(十二)----磁盘管理之 认识ext文件系统(转)

    认识ext文件系统 硬盘组成与分割 文件系统特性 Linux 的 EXT2 文件系统(inode) 与目录树的关系 EXT2/EXT3 文件的存取与日志式文件系统的功能 Linux 文件系统的运行 挂 ...

  7. 第8天【文件系统挂载、ext文件系统及read命令、Linux RAID、lvm应用】

    文件系统挂载与管理工具(01)_recv 文件系统管理: 将额外文件系统与根文件系统某现存的目录建立关联关系,进而使得此目录作为其他文件访问入口的行成为挂载: 解除此关联关系的过程 吧设备关联挂载点: ...

  8. linux系统ext文件系统知识

    ext2文件系统细节 我们都知道,操作系统中的数据分为文件内容和文件属性两部分,其中文件内容就是文件的实体数据,而文件属性就是文件类型.权限.属主.修改时间等信息.操作系统会将上述文件的内容放入磁盘文 ...

  9. atitit.ntfs ext 文件系统新特性对比

    atitit.ntfs ext 文件系统新特性对比 1. 现代文件系统应该有的特性2 1.1. 恢复Log2 1.2. 压缩2 1.3. Meta ext2 1.4. Fulltextཟsearch  ...

随机推荐

  1. js中‘0’到底是 true 还是 false

    if ('0') alert("'0' is true");  if ('0' == false) alert("'0' is false");结果是,两次都 ...

  2. CSP 最大的矩形(201312-3)

    问题描述 在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1 ≤ i ≤ n)个矩形的高度是hi.这n个矩形构成了一个直方图.例如,下图中六个矩形的高度就分别是3, 1, 6, 5, 2, 3 ...

  3. table表格的无缝循环

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Java服务,内存OOM问题如何快速定位? (转)

    转自:公众号  架构师之路 问题:有一个Java服务出现了OOM(Out Of Memory)问题,定位了好久不得其法,请问有什么好的思路么? OOM的问题,印象中之前写过,这里再总结一些相对通用的方 ...

  5. Css几个兼容性问题

    1.BUG_fireFox!!!一个容器内的子容器如果要左右浮动的话,需要在这个容器设置上样式:"overflow:hidden". 注:内部元素浮动就会导致外面的容器的高度在fi ...

  6. ListVie的用法

    1.在布局中放入一个listView <ListView android:id="@+id/list_view" android:layout_width="mat ...

  7. 【electronjs入门教程 】electronjs 介绍

    官网地址:https://electronjs.org/ 官网文档地址:https://electronjs.org/docs/ electronjs使用 JavaScript, HTML 和 CSS ...

  8. linux下NVIDIA GPU驱动安装最简方式

    之前一节已经写到了,上次的GPU driver驱动安装并不成功,因此,这次换了一种方式,比较傻瓜,但是很好使. 首先使用命令查看显示器的设备(请将显示器插在显卡上,如果插在集显上可能信息不正常) su ...

  9. linux下sendmail邮件系统安装详情

    介绍 sendmail是linux系统中一个邮箱系统,如果我们在系统中配置好sendmail就可以直接使用它来发送邮箱.sendmail的配置文件/etc/mail/sendmail.cf       ...

  10. Redis主从配置以及哨兵模式

    Redis主从模式,应用写master,读slave,减轻master的压力. 配置主结点: daemonize yes port 6379bind 0.0.0.0 pidfile /opt/redi ...