每个注册的文件系统都用一个类型为file_system_type的对象来表示:
struct file_system_type {
const char *name;/* 文件系统名 */
int fs_flags; /* 文件系统类型标志 */
int (*get_sb) (struct file_system_type *, int, /* 读超级块的方法 */
const char *, void *, struct vfsmount *);
void (*kill_sb) (struct super_block *); /* 删除超级块的方法 */
struct module *owner; /* 指向实现文件系统的模块的指针 */
struct file_system_type * next; /* 指向文件系统类型链表中下一个元素的指针 */
struct list_head fs_supers; /* 具有相同文件系统类型的超级块对象链表的头 */
struct lock_class_key s_lock_key;
struct lock_class_key s_umount_key;
struct lock_class_key s_vfs_rename_key;
struct lock_class_key i_lock_key;
struct lock_class_key i_mutex_key;
struct lock_class_key i_mutex_dir_key;
struct lock_class_key i_alloc_sem_key;
};
fs_flage可以取下面的值:
FS_REQUIRES_DEV:这种类型的任何文件系统必须位于物理磁盘设备上
FS_BINARY_MOUNTDATA:文件系统使用的二进制安装数据
FS_REVAL_DOT:始终在目录项高速缓存中使“.”和“..”路径重新生效(针对网络文件系统)
FS_ODD_RENAME:“重命名”操作就是“移动”
文件系统的注册通过函数register_filesystem完成:
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;
INIT_LIST_HEAD(&fs->fs_supers);//初始化链表
write_lock(&file_systems_lock);
p = find_filesystem(fs->name, strlen(fs->name));
if (*p)//已经注册?
res = -EBUSY;
else
*p = fs;//*p应该为NULL,这里将其指向了这个要注册 的文件系统
write_unlock(&file_systems_lock);
return res;
}
这个函数首先查找该文件系统是否已经注册过,如果注册过的话返回错误。注意这里定义了一个二级指针,看下find_filesystem
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;
}
这里p也为二级指针,而*p表示的才是下一个文件系统,这里返回的是二级指针,这样在register_filesystem给*p赋值的时候就使这个要注册的文件系统加入到了file_systems的链表末。