- 文件系统是以合理有效的层次结构组织的文件和目录的集合
- 在Linux中一切皆是文件,其中包含普通文件、目录、字符设备、块设备、 套接字等都是文件
- 类型不同的文件都是通过相同的API对其进行操作
文件系统 | 适用场景 | 原因 |
---|---|---|
ext2 | U盘 | ext2不写日志,对安全性要求不高,兼容FAT |
ext3 | 对稳定性要求高的地方 | ext4稳定性不高 |
ext4 | 小文件较少 | 不支持inode动态分配 |
xfs | 小文件多 | 支持inode动态分配 |
btrfs | 没有频繁的写操作 | 功能众多 |
- 通过统一的文件 I/O 系统调用API即可对系统中的任意文件进行操作而无需考虑其所在的具体文件系统格式
- 文件操作可以跨文件系统执行
- Linux文件系统与Windows文件系统区别
Unix/Linux文件系统 | Windows文件系统 |
---|---|
根目录文件系统 | 多根目录文件系统 |
文件名区分大小写 | 文件名不区分大小写 |
目录路径使用正斜杠,如/home/name | 目录路径使用反斜线,如C:\Users\zxy |
没有驱动器号,一切文件都在root目录下 | 驱动器号标记分区和设备 |
无独占访问权限 | 独占访问权限 |
- 根据上图可以看到,我们经常操作的文件函数底层调用底层内核函数,通过vfs虚拟文件系统来管理底层的不同的文件系统,所以我们不需要了解所操作的文件的文件系统为何。
- 虚拟文件系统是Linux 内核中的一个软件层,对内实现文件系统的抽象,允许不同的文件系统共存,对外向应用程序提供统一的文件系统接口。
- 为了能够支持不同文件系统,VFS 定义了所有文件系统都支持的基本的、抽象的接口和数据结构。
- 实际文件系统实现VFS 定义的抽象接口和数据结构,将自身的诸如文件、目录等概念在形式上与VFS的定义保持一致,在统一的接口和数据结构下隐藏了具体的实现细节。
VFS
VFS中的数据结构
- 超级块(super block):用于存储文件系统的控制信息的数据结构。描述文件系统的状态、文件系统类型、大小、区块数、索引节点数等,存放于磁盘的特定扇区中。
- 索引节点(inode):用于存储文件的元数据(文件的基本信息)的一个数据结构,包含诸如文件的大小、拥有者、创建时间、磁盘位置等信息。
- 目录项(dentry):目录被用来容纳文件,目录可以包含子目录,层层嵌套以形成 文件路径。
- 文件对象(file):一组在逻辑上具有完整意义的信息项的系列。
VFS-超级块(super block)
- 超级块用来描述整个文件系统的信息。每个具体的文件系统都有各自的超级块
- VFS超级块是各种具体文件系统在安装时建立的,并在卸载时被自动删除,其数据结构是 super_block
- 所有超级块对象以双向环形链表的形式链接在一起
struct super_block {
struct list_head s_list; /* Keep this first */
dev_t s_dev; /* search index; _not_ kdev_t 具体文件系统的块设备标识符*/
unsigned long s_blocksize; //以字节为单位数据块的大小
unsigned char s_blocksize_bits; //块大小的值占用的位数
unsigned char s_dirt;
unsigned long long s_maxbytes; /* Max file size */
struct file_system_type *s_type; //指向文件系统的file_system_tyep数据结构的指针
const struct super_operations *s_op;//指向具体文件系统的用于超级块操作的函数集合
struct dquot_operations *dq_op;
struct quotactl_ops *s_qcop;
struct export_operations *s_export_op;
unsigned long s_flags;
unsigned long s_magic;
struct dentry *s_root;
struct rw_semaphore s_umount;
struct mutex s_lock;
int s_count;
int s_syncing;
int s_need_sync_fs;
atomic_t s_active;
#ifdef CONFIG_SECURITY
void *s_security;
#endif
struct xattr_handler **s_xattr;
struct list_head s_inodes; /* all inodes */
struct list_head s_dirty; /* dirty inodes */
struct list_head s_io; /* parked for writeback */
struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */
struct list_head s_files;
struct block_device *s_bdev;
struct mtd_info *s_mtd;
struct list_head s_instances;
struct quota_info s_dquot; /* Diskquota specific options */
int s_frozen;
wait_queue_head_t s_wait_unfrozen;
char s_id[32]; /* Informational name */
void *s_fs_info; /* Filesystem private info */
/*
* The next field is for VFS *only*. No filesystems have any business
* even looking at it. You had been warned.
*/
struct mutex s_vfs_rename_mutex; /* Kludge */
/* Granularity of c/m/atime in ns.
Cannot be worse than a second */
u32 s_time_gran;
/*
* Filesystem subtype. If non-empty the filesystem type field
* in /proc/mounts will be "type.subtype"
*/
char *s_subtype;
};
VFS-索引节点(inode)
- 文件系统处理文件所需要的所有信息都放在称为索引节点的数据结构inode中
- 具体文件系统的索引节点是存放在磁盘上的,是一种静态结构,要使用它,必须调入内存,填写VFS的索引节点,因此,也称VFS索引节点是动态节点
- 文件名可以随时更改,但是索引节点对文件是唯一的,并且随文件的存在而存在
- 每个inode节点的大小,一般是128字节或256字节
VFS-目录项对象(dentry)
- 每个文件除了有一个索引节点inode数据结构外,还有一个目录项dentry数据结构。
- dentry结构代表的是逻辑意义上的文件,描述的是文件逻辑上的属性,目录项对象在磁盘上并没有对应的映像
- inode结构代表的是物理意义上的文件,记录的是物理上的属性,对于一个具体的文件系统,其inode结构在磁盘上就有对应的映像
-
一个索引节点对象可能对应多个目录项对象
VFS-文件对象(file)
- 进程是通过文件描述符来访问文件的
- Linux中专门用了一个file文件对象来保存打开文件的文件位置,这个对象称为打开的文件描述(open file description)
- 文件描述符是用来描述打开的文件的。每个进程用一个files_struct结构来记录文件描述符的使用情况,这个files_struct结构称为用户打开文件表,它是进程的私有数据
- file结构中主要保存了文件位置,此外,还把指向该文件索引节点的指针也放在其中。file结构形成一个双链表,称为系统打开文件表。
VFS数据结构之间的关系
- 超级块是对一个文件系统的描述
- 索引节点是对一个文件物理属性的描述
- 目录项是对一个文件逻辑属性的描述
-
一个进程所处的位置是由fs_struct来描述的,而一个进程(或用户)打开的文件是由files_struct来描述的,而整个系统所打开的文件是由file结构来描述
文件系统的注册和注销
- 当内核被编译时,就已经确定了可以支持哪些文件系统,这些文件系统在系统引导时,在 VFS 中进行注册。
- VFS的初始化函数用来向VFS注册,即填写文件注册表file_system_type数据结构
- 注册调用register_filesystem()函数
- 注销即删除一个file_system_type 结构,需调用 unregister_filesystem()函数
文件系统的安装
- 安装一个文件系统实际上是安装一个物理设备
- 自己(一般是超级用户)安装文件系统时,需要指定三种信息:文件系统的名称、包含文件系统的物理块设备、文件系统在已有文件系统中的安装点。
- $ mount -t iso9660 /dev/hdc /mnt/cdrom 其中,iso9660是光驱文件系统的名称,/dev/hdc是包含文件系统的物理块设备,/mnt/cdrom就是将要安装到的目录,即安装点。
- 在用户程序中要安装一个文件系统则可以调用mount()系统调用。安装过程主要工作是创建安装点对象,将其挂接到根文件系统的指定安装点下,然后初始化超级块对象,从而获得文件系统基本信息和相关的操作。
文件系统的卸载
- 如果文件系统中的文件当前正在使用,该文件系统是不能被卸载的
- 否则,查看对应的 VFS 超级块,如果该文件系统的 VFS 超级块标志为“脏”,则必须将超级块信息写回磁盘
- 之后,对应的 VFS 超级块被释放,vfsmount 数据结构将从vfsmntlist 链表中断开并被释放
- 具体的实现代码为fs/super.c中的sys_umount()函数
版权声明:本文为yeyueyouhun原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。