• APUE Unix/Linux文件系统


    1. 磁盘布局

    1.1 分区

    一个磁盘可分为多个分区, 每个分区须先用格式化工具(如mkfs)格式化成指定格式的文件系统, 才能用于存储文件. 

    磁盘文件系统布局:

    1.2 块

    block,  文件系统中的最小存储单位, 大小在格式化时规定

    设置方式, 格式化时输入命令:

    $ mke2fs -b 1024 # 通常1024, 2048, 或 4096

    1.3 自举块/启动块/Boot Block

    用于存放磁盘分区信息和启动信息, 其大小是确定的, ext2文件系统启动块大小是1KB, 由PC标准规定. 任何文件系统都不能使用启动块. 启动块之后, 才是ext2文件系统.

    1.4 柱面组/块组/Block Group

    分区 = 自举块 + 超级块 + 柱面组0..n. 每个柱面组大小一样.

    而柱面组 = 超级块 + 配置信息 + i节点图 + 块位图 + i节点数组(i节点0..m) + 数据块

    柱面组组成:

    1) 超级块/Super Block

    描述整个分区的文件系统信息, 例如块大小, 文件系统版本号, 上次mount(挂载)时间等.

    超级块在每个块组开头都有一份拷贝(图中称为超级块副本).

    超级块丢失 => 整个块组的数据丢失

    2) 配置信息

    在ext2~4文件系统中, 这部分称为块组描述符表(GDT, Group Descriptor Table), 由很多块组描述符组成, 本分区有多少个块组就有多少个块组描述符.

    每个块组描述符(Group Descriptor)存储一个块组的描述信息, 如该块组从哪儿开始是inode表(i节点数组), 从哪儿开始是数据块(Data Blocks), 空闲inode和数据块还有多少个等.

    同超级块, 块组描述符在每个块组的开头也有一份拷贝.

    块组描述符丢失 => 整个块组的数据丢失

    3) i节点图/inode Bitmap

    本身占一个块, 如4096byte (4KB),  其中每个bit表示一个inode(i节点)是否空闲.

    4) 块位图/Block Bitmap

    每个bit位代表本块组中的一个块是否空闲,

    - 1 表示该块已用;

    - 0 表示该块空闲;

    一个块组(Block Group, 柱面组)中的块是这样利用的:

    数据块存储所有文件的数据, 如某个分区的块大小1024byte, 某个文件2049byte, 就需要3个数据块存储: 前2个数据块都存放1024byte, 第3个数据块存放1byte;

    5)i节点数组/inode Table

    inode这里的i可用理解成information node, inode Table专门用于存放文件的描述信息(区别于文件数据), 如文件类型(常规, 目录, fifo文件, 符号链接等), 访问权限, 文件大小, 创建、最后一次修改/访问时间(可用ls -l命令查询).

    每个文件都有一个inode, 一个块组(Block Group)中所有inode组成inode表.

    inode表总共占多少个块在格式化的时候, 就要决定并写入块组描述符, 由GDT/配置信息管理. mke2fs(格式化工具)的默认策略是一个块组有多少个8KB, 就分配多少个inode.

    mke2fs -i命令可以手动指定每多少个字节分配一个inode.

    6) 数据块/Data Blocks

    不同文件类型, 有不同的存储情况:

    • 常规文件

    文件的数据存储在数据块中

    • 目录

    目录下所有文件名和目录名存放在数据块中,  除文件名外, ls -l命令查看到的所有信息都保存在inode中.

    注意: 文件名是存放在所在目录的数据块中, 而非inode中.

    • 符号链接

    符号链接的文件内容就是目标路径名. 

    如果目标路径名较短, 则直接保存在inode中, 以便快速查找; 如果目标路径名较长, 则分配一个数据块来保存.

    ---- 疑问: 何为路径名较短, 标准是什么? 如何查看和设置?

    • 设备文件/FIFO/socket等特殊文件

    没有数据块, 设备文件的主设备号和此设备号, 保存在inode中.

    创建testdir后的文件系统实例, 表明硬链接所代表的链接计数如何计算.

    注意:

    1. 叶子目录(没有子目录的目录)链接计数为2, 分别是"."和命名该目录的目录项(我的理解一般是"..");

    2. 普通文件(非目录)链接计数为1, 因为只有当前目录(".", 普通文件的父目录)指向普通文件;

    3. (link)不允许构造指向目录的硬链接, 因为一旦构成循环的硬链接, 很难消除;

    硬链接和符号链接的区别:

    1)inode链接计数

    硬链接是文件的别名, 每增加一个, 文件对应的i节点的链接计数+1. 链接计数表示, 目录块中指向i节点编号的目录项的个数;

    符号链接是文件的间接指针, 其文件内容直接存储链接的文件的路径名, 不会影响链接计数;

    2)所处位置

    硬链接一般要求链接和文件位于同一个文件系统中;

    符号链接没有这个限制;

    3)创建权限

    只有root用户才能创建硬链接;

    符号链接没有这个限制;

    具体验证方法, 可查看下面的实验.

    2. FAQ

    2.1 如何查看一个数据块的大小(Block Size)?

    参见 Linux查看系统块大小

    (1)stat查看 根目录"/" 所在磁盘分区的Block Size

    $ stat -f /
      文件:"/"
        ID:7e5c5070d17ef5e7 文件名长度:255     类型:ext2/ext3
    块大小:4096       基本块大小:4096
        块:总计:7220231    空闲:3479622    可用:3107091
    Inodes: 总计:1843200    空闲:1533150

    这里4096(byte)就是Block Size

    (2)fdisk -l查看指定磁盘分区的Block Size (/dev/sda?,  根据实际需要查询的分区决定)

    $ sudo fdisk -l /dev/sda6
    Disk /dev/sda6:44 GiB,47227863040 字节,92241920 个扇区
    单元:扇区 / 1 * 512 = 512 字节
    扇区大小(逻辑/物理):512 字节 / 4096 字节
    I/O 大小(最小/最佳):4096 字节 / 4096 字节

    这里4096就是Block Size

    (3) tune2fs命令查看指定分区的Block Size

    $ sudo tune2fs -l /dev/sda6 | grep "Block size"
    Block size:               4096

    (4)blockdev命令查看指定分区的Block Size

    $ sudo blockdev --getbsz /dev/sda6
    4096

    2.2 如何查看文件系统类型?

    使用lsblk命令, 参见 如何查看linux文件系统类型?

    $ lsblk -f

    2.3 如何创建并查看符号链接?

    使用ln -s命令创建, ls -l命令查看

    如果已经有了hello文件, 则不用touch命令创建. 用ln命令创建了halo后, 发现hello的硬链接数1不变, 而halo文件大小为7byte, 即内容文件名./hello (7个字符).

    $ touch hello
    $ ln -s ./hello halo
    $ ls -l
    总用量 0
    lrwxrwxrwx 1 martin martin 7 5月  15 00:59 halo -> ./hello
    -rw-r--r-- 1 martin martin 0 5月  15 00:58 hello
    

    2.4 如何创建并查看硬链接?

    假设已经用touch命令创建了hello. 在用ln命令创建了hello2后, 发现hello的硬链接数由原来的1变成了2, 而且新建的硬链接文件hello2链接数也是2(与hello一样).

    我们知道, 普通文件硬链接数一般是1, 也就是说, 如果一个普通文件硬链接数>1, 说明有其他硬链接文件指向了该文件.

    $ ln ./hello hello2
    $ ls -l
    总用量 0
    lrwxrwxrwx 1 martin martin 7 5月  15 00:59 halo -> ./hello
    -rw-r--r-- 2 martin martin 0 5月  15 00:58 hello
    -rw-r--r-- 2 martin martin 0 5月  15 00:58 hello2

    2.5 如果往文件写入数据, 是否会影响符号链接文件/硬链接文件?

    往文件hello写3个字符"abc", 可以看到, 符号链接文件hallo并未受到影响, 而硬链接文件helo2文件大小改变.

    $ cat hello
    abc
    $ ls -l
    总用量 8
    lrwxrwxrwx 1 martin martin 7 5月  15 00:59 halo -> ./hello
    -rw-r--r-- 2 martin martin 4 5月  15 01:05 hello
    -rw-r--r-- 2 martin martin 4 5月  15 01:05 hello2

    3. 参考

    Ext4文件系统架构分析(一)

  • 相关阅读:
    【学习笔记】《Java编程思想》 第1~7章
    CodeForces
    第十六届浙江大学宁波理工学院程序设计大赛 E 雷顿女士与平衡树(并查集)
    第十六届浙江大学宁波理工学院程序设计大赛 D 雷顿女士与分队hard version(dp)
    CodeForces 862B(思维+二分图染色)
    CodeForces
    CodeForces
    CodeForces
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/fortunely/p/14770668.html
Copyright © 2020-2023  润新知