Linux文件系统之VFS(八)
文件系统的注册和安装是两个不同的概念。注册是指向内核生命自己可以被支持,但是可以被支持与能够被访问是两码事,仅仅只是一个文件系统,我们是不可能访问它的。为了能够被访问,文件系统还必须被安装到系统中,也就是mount
操作。
文件系统注册
如果文件系统是作为可加载的模块,则在模块加载的时候进程注册。比如说,isofs
文件系统编译为一个模块时,在模块加载的过程中,会调用初始化函数init_iso9660_fs()
,该函数使用register_filesystem
将自己的file_system_type
对象iso9660_fs_type
注册到内核里。
如果文件系统不是可加载的模块,比如说sysfs
,同样必须使用register_filesystem()
将自己的file_system_type
对象注册到内核里。register_filesystem()
的任务就是将指定文件系统的file_system_type
对象向内核注册,所以已注册文件系统的file_system_type
对象形成一个链表,链表头是fs/filesystems.c
文件中定义的全局变量file_systems
,
static struct file_system_type *file_systems;
static struct file_system_type **find_filesystem(const char *name, unsigned len)
{
struct file_system_type **p;
for (p=&file_systems; *p; p=&(*p)->next)
if (strlen((*p)->name) == len &&
strncmp((*p)->name, name, len) == 0)
break;
return p;
}
int register_filesystem(struct file_system_type * fs)
{
int res = 0;
struct file_system_type ** p;
BUG_ON(strchr(fs->name, '.'));
if (fs->next)
return -EBUSY;
write_lock(&file_systems_lock);
p = find_filesystem(fs->name, strlen(fs->name));
if (*p)
res = -EBUSY;
else
*p = fs;
write_unlock(&file_systems_lock);
return res;
}
int unregister_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;
write_lock(&file_systems_lock);
tmp = &file_systems;
while (*tmp) {
if (fs == *tmp) {
*tmp = fs->next;
fs->next = NULL;
write_unlock(&file_systems_lock);
synchronize_rcu();
return 0;
}
tmp = &(*tmp)->next;
}
write_unlock(&file_systems_lock);
return -EINVAL;
}
文件系统安装
一个文件系统只有安装后才能够被访问。除了根文件系统系统是在内核引导阶段就被安装之外,其他文件或者由初始化脚本安装,或者由用户使用mount命令安装在已安装文件系统的某一个目录上。
每个文件系统都有自己的根目录,安装文件系统的那个目录成为安装点,已安装文件系统的根目录隐藏了安装点目录原来的内容。
在众多的文件系统中,之所以单独介绍rootfs的注册和安装,是因为它对于VFS的重要性。rootfs可以说是VFS存在的基础,它为其他文件系统提供一个作为初始安装点的空目录。
- 注册rootfs
init_rootfs
在init/do_mounts.c
文件中定义,他仅是通过调用register_filesystem()
将自己的file_system_type
对象rootfs_fs_type
注册到内核中。其定义如下所示:
static struct file_system_type rootfs_fs_type = {
.name = "rootfs",
.mount = rootfs_mount,
.kill_sb = kill_litter_super,
};
- 安装rootfs
init_mount_tree
在fs/namespace.c
文件中定义,主要完成一下工作:
- 调用vfs_kern_mount来安装rootfs;
- 切换当前进程的根目录和当前目录为“/”.