在VFS框架下编写一个文件系统是十分方便的,只需要实现VFS需要用到的接口即可,大量磁盘文件系统被加入了进来。除此之外,很多“虚拟”的文件系统也被创造出来,为内核提供了很多重要特性。本篇来梳理一下Linux文件系统的类型,以及以ext4为例来看看一个文件系统驱动是如何被实现的。
文件系统类型
再来回顾一下之前梳理的文件系统框架:
文件系统根据底层操作的硬件,基本可分为四类:
普通文件系统
传统意义的磁盘文件系统,是文件系统驱动占比最大的部分,用于访问磁盘上的数据。
内存文件系统
底层存储介质是内存的文件系统,常见的是tmpfs和ramfs。系统中/tmp目录被挂载为tmpfs,主要用于存放临时文件,系统重启即会清空。内存文件系统还在kernel启动时起到关键作用,kernel启动时各分区及关键驱动可能还没加载,此时通常先挂载一个基于内存的根文件系统initramfs,在其中完成系统初始化工作,再将rootfs切换到真正的根文件系统磁盘。
网络文件系统
nfs可以基于网络来共享本地数据或者访问远端设备的数据。nfs并不处理文件系统的实际操作,只是提供基于rpc协议的网络客户端与服务端程序。当共享本地数据时启动服务端,将收到的网络请求转换为对共享目录的操作。当访问远端设备时启动客户端,将文件读写等操作转换为网络请求发出。
特殊文件系统
Linux中的"文件",除了代表磁盘上真实的文件,还可以是对系统及硬件资源操作访问的入口。Linux用一些特殊的文件系统来管理这些文件。例如,devtmpfs用于管理设备节点文件,proc,sysfs中的文件用于访问内核运行时的一些数据结构。
关键接口
VFS框架提供了大量接口,编写一个文件系统驱动不需要全部实现,VFS也提供一些通用的接口可以直接使用。这里列出一些关键接口及其作用。
file_system_type
struct file_system_type用于描述一个文件系统类,是最先需要定义的结构,其中最重要的是实现mount接口。
- mount() , 挂载一个该类型文件系统实例时被调用,创建super_block以及根目录dentry,并初始化。
super_operations
管理文件系统整体信息的接口,主要功能是对inode资源的管理。
- alloc_inode(),在内存中分配一个inode并初始化,通常文件系统驱动会自己定义一个更大的结构并内嵌inode。
- write_inode(),将一个inode写入磁盘。
- evict_inode(),删除一个inode。