因为linux支持模块机制,所以我们可以将文件系统编译为模块,所以文件系统系统类型的注册的注册有多种方式:要么已经包含在内核映像中,要么作为一个模块被动态加载。我们关注的重点是rootfs和sysfs,他们其实在系统初始化的时候就注册并安装好了,没有rootfs,linux就没法玩了。以rootfs的注册为例,来分析一下文件系统类型的注册:
在start_kernel-->vfs_caches_init(totalram_pages);
vfs_caches_init函数如下:
void __init vfs_caches_init(unsigned long mempages) { unsigned long reserve; /* Base hash sizes on available memory, with a reserve equal to 150% of current kernel size */ reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1); mempages -= reserve; names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); dcache_init(); inode_init(); files_init(mempages); mnt_init(); bdev_cache_init(); chrdev_init(); }其中: dcache_init(); //目录项的缓存
目前我们关注的重点是mnt_init(),其中有这么几行代码:
err = sysfs_init(); if (err) printk(KERN_WARNING "%s: sysfs_init error: %d\n", __func__, err); fs_kobj = kobject_create_and_add("fs", NULL); if (!fs_kobj) printk(KERN_WARNING "%s: kobj create error\n", __func__); init_rootfs(); init_mount_tree();可以看到,sysfs_init还在init_rootfs之前,是不是有点奇怪,没有root fs,哪有其他的fs啊?这个在后面我们会明白。
这一次我们只看init_rootfs():
在fs/ramfs/inode.c中:
int __init init_rootfs(void) { int err; err = bdi_init(&ramfs_backing_dev_info); if (err) return err; err = register_filesystem(&rootfs_fs_type); if (err) bdi_destroy(&ramfs_backing_dev_info); return err; }register_filesystem(&rootfs_fs_type);完成文件系统的注册:
static struct file_system_type rootfs_fs_type = { .name = "rootfs", .get_sb = rootfs_get_sb, .kill_sb = kill_litter_super, };rootfs_fs_type是一个file_system_type类型的结构体,主要的函数是get_sb--rootfs_get_sb函数,作用是获取rootfs文件系统的超级块对象。
其实这个注册过程很简单,其实就是加入链表的过程:
为了证明链表的存在:还是要给出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 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; };
往后,我们会看到这两个链表各自是怎么串的,串的是什么内容。而在register_filesystem中我们就可以看到struct file_system_type * next;单项链表的形成。
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; //1 INIT_LIST_HEAD(&fs->fs_supers); //2 write_lock(&file_systems_lock); p = find_filesystem(fs->name, strlen(fs->name)); //3 if (*p) res = -EBUSY; else *p = fs; write_unlock(&file_systems_lock); return res; }1、如果文件系统已经注册了,那么无法在注册了。每种类型的文件系统只能注册一次,但是可以有多种设备使用同一个类型的文件系统,也可以将同一类型的文件系统 挂载在不同的路径下。
2、初始化fs->fs_supers;
3、将即将注册的文件系统放在链表的尾部:
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; }
到此,文件系统类型的注册就结束了,简单说:就是将文件类型加入以file_systems为表头的单向链表中。