Linux操作系统--文件系统

文件系统

1. 文件系统特性

  • 一切皆文件
  • 采取树形结构
  • 对热点文件进行缓存
  • 采用索引,便于查找分类
  • 记录哪些文档正在被哪些任务使用

2. 磁盘结构

磁盘-》盘片-》磁道-》扇区(每个扇区512bytes)

硬盘的最小存储单位就是扇区,而且硬盘本身并没有block的概念。文件系统不是一个扇区一个扇区的来读数据,太慢了,所以有了block(块)的概念,它是一个块一个块的读取的,块的大小是扇区大小的整数倍(默认4096bytes,即1个块是由连续的8个扇区组成)。

3. 文件索引节点inode

因为文件不是连续存放的,是分散成小片存放的,这样添加,删除,插入也更容易,所以需要有索引节点来维护文件的信息。

一个文件(包括文件夹)对应一个索引节点inode(即index node),ls列出的权限,用户,大小等等信息,都是inode节点的信息。


struct ext4_inode {
    __le16  i_mode;     /* File mode 文件读写权限*/
    __le16  i_uid;      /* Low 16 bits of Owner Uid 属于哪个用户*/
    __le32  i_size_lo;  /* Size in bytes 大小*/
    __le32  i_atime;    /* Access time 最近一次访问时间*/
    __le32  i_ctime;    /* Inode Change time 最近一次更改inode的时间(更改用户和权限但是没有更改数据也算更改inode)*/
    __le32  i_mtime;    /* Modification time 最近一次更改时间*/
    __le32  i_dtime;    /* Deletion Time */
    __le16  i_gid;      /* Low 16 bits of Group Id 用户组*/
    __le16  i_links_count;  /* Links count */
    __le32  i_blocks_lo;    /* Blocks count 占用多少块*/
    __le32  i_flags;    /* File flags */
......
    __le32  i_block[EXT4_N_BLOCKS];/* Pointers to blocks 存储文件内容的地方*/
    __le32  i_generation;   /* File version (for NFS) */
    __le32  i_file_acl_lo;  /* File ACL */
    __le32  i_size_high;
......
};

文件保存在i_block里(ext2和ext3里一个inode默认有12个用于存储文件的块),如果文件过大,就让指针指向间接块,间接块里面存储数据块的位,如果文件更大,就再加一层间接块。

问题: 读取大文件需要多次读取硬盘,速度变慢。

Extents

Ext2,Ext3,Ext4都是linux的文件系统格式。

Ext2/3 采用间接块映射,当操作大文件时,效率极其低下。比如一个 100MB 大小的文件,在 Ext3 中要建立 25,600 个数据块(每个数据块大小为 4KB)的映射表。

Ext4 引入了现代文件系统中流行的 extents 概念,每个 extent 为一组连续的数据块,上述文件则表示为“该文件数据保存在接下来的 25,600 个数据块中”,提高了不少效率。

位图bitmap

在向硬盘存储数据时,文件系统需要知道哪些块是空闲的,位图只使用0和1标识对应block是空闲还是被占用。

为什么位图更高效?

在位图中1个字节8个位,可以标识8个block。对于一个block大小为1KB、容量为1G的文件系统而言,block数量有10241024个,所以在位图中使用10241024个位共1024 * 1024 / 8 = 131072字节 = 128K,即1G的文件只需要128个block做位图就能完成。通过扫描这100多个block就能知道哪些block是空闲的,速度提高了非常多。

但是要注意,bmap的优化针对的是写优化,因为只有写才需要找到空闲block并分配空闲block。对于读而言,只要通过inode找到了block的位置,cpu就能迅速计算出block在物理磁盘上的地址,cpu的计算速度是极快的,计算block地址的时间几乎可以忽略,那么读速度基本认为是受硬盘本身性能的影响而与文件系统无关。大多数稍大一点的文件可能都会存储在不连续的block上,而且使用了一段时间的文件系统可能会有不少碎片,这时硬盘的随机读取性能直接决定读数据的速度,这也是机械硬盘速度相比固态硬盘慢的多的多的原因之一,而且固态硬盘的随机读和连续读取速度几乎是一致的,对它来说,文件系统碎片的多少并不会影响读取速度。

虽然bmap已经极大的优化了扫描,但是仍有其瓶颈:如果文件系统是100G呢?100G的文件系统要使用128*100=12800个1KB大小的block,这就占用了12.5M的空间了。试想完全扫描12800个很可能不连续的block这也是需要占用一些时间的,虽然快但是扛不住每次存储文件都要扫描带来的巨大开销。

所以需要将文件系统划分开形成块组。

目录

目录也是文件, 也有 inode, inode 指向一个块, 块中保存各个文件信息, ext4_dir_entry 包括文件名和 inode, 默认按列表存。

可添加索引, 加快文件查找:用索引项 dx_entry 保存文件名哈希和块的映射, 若该块不是索引, 则里面保存 ext4_dir_enry 列表, 逐项查找。

软链接 硬链接

  1. 链接即文件的别名: ln -s 创建软链接; ln 创建硬链接
  2. 硬链接与原始文件共用一个 inode, 但不能跨文件系统
  3. 软链接是一个文件, 有自己的inode, inode中的数据块保存对原始文件的指针, 可跨文件系统

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!