一、先了解一下什么是挂载
Linux有自己的一套文件系统,例如Ext2、Ext3,但是外部其他文件系统时,由于各个文件系统都各自有一套的文件管理体系,是无法通过Linux本身访问文件的方式直接访问的,这个时候挂载就产生了。
挂载,指的就是将设备文件中的顶级目录连接到 Linux 根目录下的某一目录(最好是空目录),访问此目录就等同于访问设备文件。
举个例子:将U盘插入Linux系统中,虽然可以通过图形界面查看设备信息,但是无法通过命令方式访问数据,访问此目录只会提供给你此设备的一些基本信息(比如容量),如下图所示,两边的文件系统结构是不相同的。
Linux根目录的/dev目录下存放的是所有的硬件设备文件,事实上,当 U 盘插入 Linux 后,系统也确实会给 U 盘分配一个目录文件(比如 sdb1),就位于 /dev/ 目录下(/dev/sdb1)。
将/sdb1挂载到/sdb-u文件目录下
mount /dev/sdb1 /sdb-u
可以看到,U 盘文件系统已经成为 Linux 文件系统目录的一部分,此时访问 /sdb-u/ 就等同于访问 U 盘。
二、VFS基本概念
之所以挂载后可以使Linux成功访问U盘,是因为存在一种机制:VFS虚拟文件系统
它屏幕了底层各个文件系统的差异,提供一套通用的接口,所有文件系统都需要先转换为VFS结构才能为用户所调用。当上面将/dev/sbd1挂载到/sbd-u下时,就相当于将U盘特有的文件系统转换成了VFS结构
VFS本身只存在于内存中,它需要将硬盘上的文件系统抽象到内存中,这个过程主要是由以下几个重要结构来实现的
1、超级快 supper_block
超级块(super_block)代表了整个文件系统本身,超级块的内容需要读取具体文件系统在硬盘上的超级块结构获得,所以超级块是具体文件系统超级块的内存抽象
超级块的结构非常负责,将其简化后的数据结构如下所示
struct super_block {
unsigned long s_blocksize;
unsigned char s_blocksize_bits;
unsigned long s_maxbytes;
struct file_system_type *s_type;
struct super_operations *s_op;
unsigned long s_magic;
struct dentry *s_root;
struct list_head s_inodes;
struct list_head s_dirty;
struct block_device *s_bdev;
void *s_fs_info;
}
❑ s_blocksize 指定了文件系统的块大小
❑ s_maxbytes 指定文件系统中最大文件的尺寸
❑ s_type 指向file_system_type结构的指针
❑ s_magic 是魔术数字,每个文件系统都有一个魔术数字
❑ s_root 是指向文件系统根dentry的指针
-----超级块对象还定义了一些链表头,用来链接文件系统内的重要成员-----
❑ s_inodes 指向文件系统内所有的inode,通过它可以遍历inode对象
❑ s_dirty 指向所有dirty的inode对象
❑ s_bdev 指向文件系统存在的块设备指针
-----超级块结构包含一些函数指针-----
❑ super_operations 提供了最重要的超级块操作,它的成员函数read_inode提供了读取inode信息的功能。每个具体的文件系统一般都要提供这个函数来实现对inode信息的读取,例如ext2文件系统提供的具体函数是ext2_read_inode。我们可以理解为这就是:VFS提供了架构,而具体文件系统必须按照VFS的架构去实现
超级块链表
每个超级块都要链接到一个超级块链表super_blocks,而文件系统内的每个文件在打开时都需要在内存分配一个inode结构,这些inode结构都要链接到超级块,最后形成类似以下的结构,遍历super_blocks就能找到操作系统打开过的所有inode。