文件系统中的核心数据结构
宏观上文件系统在kernel的形态
- 文件系统运作流程按照:vfs->磁盘缓存->实际磁盘文件系统->通用块设备层->io调度层->块设备驱动层->磁盘。具体流程的详细展现如下如
如何理解文件系统中的数据结构?
- linux中文件系统还有几种核心数据结构分别是
super_block
、inode
、dentry
、file
.super_block
是磁盘文件系统(xfs/ext4)的内存呈现,inode
是linux中文件唯一呈现,也是文件本身,存储了文件的元数据。dentry
是文件本身的代表,存储了文件的名称和inode.file
是文件被打开的状态,每个进程执行文件的系统调用都会实例化file
。每一数据结构都会有一些列的函数表定义和私有数据。这个是为了实现不同文件系统而采用的工厂设计模式,这些私有数据是vfs和实际磁盘文件系统交互的核心数据结构。每个实际的磁盘文件系统(ext4/xfs)文件系统针对super_block
、inode
、dentry
、file
.super_block
都会有自己的操作实现,kernel只需要把定义通用接口,这些接口的具体实现都是有实际磁盘文件系统注册后把这些接口操作给实例化,这就达到了vfs和实际文件系统的交互。
struct super_block
简单描述
代码语言:javascript
代码运行次数:0
运行
AI代码解释
// struct super_block 省略和一些字段,比较核心的字段描述了下
struct super_block {// 把suoer_block链接到s_list链表 struct list_head s_list; // s_blocksize的位数unsigned char s_blocksize_bits;// 文件系统中块大小unsigned long s_blocksize;// 支持最大文件大小loff_t s_maxbytes; // 文件系统类型struct file_system_type *s_type;// super_block的操作函数const struct super_operations *s_op;// dentry函数操作定义const struct dentry_operations *s_d_op;// dentry的指针,指向根节点的rootstruct dentry *s_root;// 挂载该文件系统的挂载点组成的链表struct list_head s_mounts; // 同一种文件系统组成的链表struct hlist_node s_instances;// 实际文件系统的私有数据void *s_fs_info; } __randomize_layout;
struct file_system_type
简单描述
代码语言:javascript
代码运行次数:0
运行
AI代码解释
// 每个文件系统在实话时候都会先注册这个文件系统,fs_system_type就是用来描述这个文件系统的
struct file_system_type {// 文件系统名称,比如ext4、xfsconst char *name;// 实际文件提供的mount函数用来初始化super_blockstruct dentry *(*mount) (struct file_system_type *, int,const char *, void *);// 释放文件系统的哈数void (*kill_sb) (struct super_block *);// 内核模块描述struct module *owner;// file_system_type链表struct file_system_type * next;// 同一种文件系统super_block组成的链表struct hlist_head fs_supers;
};// 比如ext4的file_system_type的类型
static struct file_system_type ext4_fs_type = {.owner = THIS_MODULE,.name = "ext4",.mount = ext4_mount,.kill_sb = kill_block_super,.fs_flags = FS_REQUIRES_DEV,
};
struct inode
简单描述
代码语言:javascript
代码运行次数:0
运行
AI代码解释
// 文件系统中inode描述,其中说明了核心字段的函数
struct inode {// 文件类型umode_t i_mode;// uid/gid是描述文件的属主kuid_t i_uid;kgid_t i_gid;// inode的操作函数,这个是由具体文件系统决定const struct inode_operations *i_op;// inode属于的超级快struct super_block *i_sb;// page cache涉及到缓存管理struct address_space *i_mapping;// inode的编号,单个文件系统内这个是唯一的unsigned long i_ino;// inode所指向的文件大小loff_t i_size;// 文件的acess/mofidy/change时间struct timespec64 i_atime;struct timespec64 i_mtime;struct timespec64 i_ctime;// inode链接到哈希链表中struct hlist_node i_hash;// inode链接到super_block上struct list_head i_sb_list;union {// 进程打开文件时候的操作函数,这个是与文件类的系统调用对接const struct file_operations *i_fop; void (*free_inode)(struct inode *);};// inode的私有数据,一般存储实际文件系统的私有数据void *i_private; /* fs or device private pointer */
} __randomize_layout;
- inode在i_mapping是用缓存,其具体的关系如下
struct dentry
简单描述
代码语言:javascript
代码运行次数:0
运行
AI代码解释
// 文件系统的目录树是采用组织dentry来呈现
struct dentry {// 指向父目录的dentrystruct dentry *d_parent;// 保存了文件名字和哈希值struct qstr d_name;// 该目录项指向的inodestruct inode *d_inode;// 当目录项名称比较短的时候保存在这里unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */// 定义dentry的操作函数,每个文件系统都针对d_op进行初始化const struct dentry_operations *d_op;// dentry私有数据void *d_fsdata; /* fs-specific data */union {struct list_head d_lru; /* LRU list */wait_queue_head_t *d_wait; /* in-lookup ones only */};// 当前dentry所有父目录项的链表struct list_head d_child; /* child of parent list *///当前目录项下所有子目录项的链表struct list_head d_subdirs; /* our children */} __randomize_layout;
struct file
简单描述
代码语言:javascript
代码运行次数:0
运行
AI代码解释
// 每当进程打开一个文件都会实例化一个struct file,这里面包含了标准的posix语义的操作
struct file {// 文件路径struct path f_path;// 文件指向的inodestruct inode *f_inode;// 定义struct file的操作函数const struct file_operations *f_op;// 文件的引用计数器atomic_long_t f_count;// 文件打开的flagsunsigned int f_flags;// 文件的modefmode_t f_mode;// 文件的当前位置loff_t f_pos;// struct file的私有数据void *private_data;// 文件的page cache相关的address_spacestruct address_space *f_mapping;} __randomize_layout
- 进程打开一个文件的呈现如下面