文章纯属个人理解,可能有误!

理解linux文件系统,需要清楚几个点:

  • 文件系统的作用?

  • 文件是如何在硬盘上存取的?

  • 文件系统和块设备之间的关系?

  • 为什么有VFS?

文件系统的作用

理解文件系统的作用,可以思考一个问题。假如没有文件系统,我们应该如何读写硬盘?如果没有文件系统,那就没有文件和目录的概念,硬盘对于我们来说就是一块可以连续读写的字节序列存储介质。假如我们有一些数据需要存储,我们需要知道磁盘上的扇区和磁道,调用磁盘驱动程序,把这些数据存储到对应的位置,这里,既需要注意不要把磁盘上已有的内容覆盖掉,又要知道下次需要读取这些数据的时候,应该从哪个地方读取多少内容,这个过程都只能手动实现。

所以,文件系统实际上是帮我们把硬盘这种块设备,以某种方式进行组织,并且帮忙我们更好的存储和索引数据,这里既要能存取数据,又要能很方便的索引,于是文件系统既有供用户使用的逻辑结构,包括目录和文件,也有内部的文件数据组织方式,包括:超级块、inode及inode表,数据块等。

文件是如何在硬盘上存取的

根据理解linux内核(第16章)书中的描述,在linux中访问普通文件的过程直接和page cache相关,当read系统调用执行时,这个调用会是阻塞状态,直到数据被拷贝到用户地址空间,当write系统调用执行时,数据被写入page cache。而读取文件,总是以page为单位,内核每次都会把page大小整数倍的数据返回给read调用,如果当进程执行read时这些文件数据不在内存中,那么内核会分配一个新的page frame,把对应的数据写入这个page,然后把这个page加入到page cache里面去,最后再把这些数据拷贝到用户进程地址空间。读取文件大致就是在块设备上找到这个文件对应的数据到底存储在哪个块上面。一旦这个数据块被定为之后,内核就会调用块设备的IO操作接口去填充新的page。这个过程对应到linux代码中就是generic_file_read。

文件系统和块设备之间的关系

我们在安装操作系统,或者使用一块新的硬盘的时候,一般会有2个操作

  • 格式化/初始化文件系统

  • 挂载mount硬盘设备

在linux中,这分别对应mkfs.ext4和mount两个命令。而这两个命令就揭示了文件系统和设备之间的关系,并且,在使用cloud init进行操作系统初始化,挂载硬盘的时候,它也是分为2个不同的配置:

fs_setup:
  - label: nvme0
    filesystem: 'ext4'
    device: '/dev/nvme0'
  - label: nvme1
    filesystem: 'ext4'
    device: '/dev/nvme1'
mounts:
 - [ /dev/nvme0, /data0 ]
 - [ /dev/nvme1, /data1 ]

当我们把一个硬盘格式化为某个文件系统的时候,实际上就是把这个硬盘初始化为某个文件系统,意思就是把这块硬盘按照指定的文件系统所要求的数数据块组织方式进行初始化,写入超级块、描述符、数据块位图、inode位图、inode表等,从这里我们也可以看出,当一个文件系统初始化的时候,它就决定了这块硬盘上的数据组织方式,比如每个数据块的大小一般为4K,而inode数也决定了到底可以创建多少文件及目录。

如果硬盘仅仅是格式化了,在linux中是不能直接访问的,还必须挂载到文件系统中的某个目录,这是因为linux只有一个根文件系统,这就是所谓的VFS,而linux本身支持多种文件系统类型,而每一种文件系统,对它的访问都必须通过VFS。

为什么有VFS?

显然,VFS是一种非常好的抽象:

  • 定义了一套文件系统的通用访问接口,支持linux的文件系统都必须实现VFS的接口

  • 把文件和目录做了统一,这样访问文件和目录就只需要一个接口

  • 不同的文件系统可以在linux中共存,甚至包括网络文件系统,以及一些特殊文件系统,真正实现了一切皆文件的思想


original refer