“一切皆文件”,刚接触Linux就听到的一个概念 ,体现了Linux的设计哲学,将一切软硬件资源都抽象为文件,使得用户可以用同样的api操作几乎所有系统资源,对应用开发带来了极大的便利,也给底层驱动的实现制定了统一的接口框架。“文件”这一概念在Linux中被重新定义,不再仅是代表磁盘上的一段数据,同时也是和系统交互的入口。在Linux中文件系统负责组织管理这些文件,还需要提供文件操作的各类接口,其概念再也不只是一种组织磁盘数据的方式,还包含了复杂的框架及策略。“文件系统”在Linux中的作用是什么?提供了哪些功能?这一系列尝试基于Linux5.x来梳理一下吧。
概述
要搞清文件系统在Linux中包含哪些功能,我的思路是直接从源码出发,看看fs/目录下到底有哪些代码,既然内核设计者将这些功能归为fs必有其道理,梳理了下其大致结构如下:
fs/中还有很大部分代码是关于IO模式的,图中未包含。总结一下文件系统在Linux内包含的功能,主要分四部分,这一系列也按此来分别讨论:
- vfs: 文件系统中各组件的抽象,相互作用关系,提供哪些操作。
- fs实现:Linux支持哪里类型的文件系统,一个文件系统需要实现哪些接口。
- cache:如何与memory子系统一起管理cache,提升IO性能。
- IO模式:针对应用程序不同的IO需求,提供哪些IO模式。
VFS
Linux文件系统的高明之处在于其强大的可扩展性及兼容性,文件系统驱动以模块的形式集成在内核中,使得各文件系统的维护与扩展十分便利。系统运行时,Linux使多种文件系统和谐共存,用户可自由地将不同磁盘或分区挂载在目录树的任何地方,之后即可使用统一接口透明的对各个文件系统进行操作,无需考虑底层差异。为了实现这种效果VFS起到了关键作用,VFS层使用了面向对象的设计方式,对文件系统进行抽象,使得任意一个文件系统都可以用固定的对象进行描述。文件系统驱动根据VFS框架实现相关方法,在用户进行操作时VFS再根据操作的文件系统类型使用不同方法完成底层处理。
VFS四个主要对象
super_block
描述一个已经挂载的文件系统,包含设备名,分区大小,blocksize等基础数据,superblock方法集合,所包含的inode链表等。superblock包含的信息众多,与磁盘上的实际数据对应,常作为入参被内外部接口引用,对它的更新也会适时同步到磁盘上。
struct super_block {
struct list_head s_list; /* Keep this first */ //sb链表指针
...
struct file_system_type *s_type; //文件系统类
const struct super_operations *s_op; //sb方法集合
...
struct dentry *s_root; //根目录dentry
...
struct hlist_node s_instances; //在s_type->fs_supers链表中的索引节点
...
/*
* Keep s_fs_info, s_time_gran, s_fsnotify_mask, and
* s_fsnotify_marks together for cache efficiency. They are frequently
* accessed and rarely modified.
*/
void *s_fs_info; /* Filesystem private info */ //各文件系统包含的信息不一样,留给驱动保存数据用
...
/*
* The list_lru structure is essentially just a pointer to a table
* of per-node lru lists, each of which has its own spinlock.
* There is no need to put them into separate cachelines.
*/
struct list_lru s_dentry_lru; //dentry lru索引节点
struct list_lru s_inode_lru; //inode lru索引节点
...
/* s_inode_list_lock protects s_inodes */
spinlock_t s_inode_list_lock ____cacheline_aligned_in_smp;
struct list_head s_inodes; /* all inodes */ //包含的所有inode链表
...
}
superblock实现的方法主要是对in