linux文件系统的系统分析--(二)文件系统类型的注册

 

因为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();   //目录项的缓存
                inode_init();      //索引节点的缓存
                files_init(mempages);   //file的缓存
                mnt_init();
                bdev_cache_init();       //块设备的缓存
                chrdev_init();             //字符设备的初始化,在《 linux设备模型之字符设备》中会看到字符设备文件是如何建立的。

        目前我们关注的重点是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;
};

          仔细看一下这个结构体,可以看到貌似有两个链表:struct file_system_type * next;单项链表和struct list_head fs_supers;这个linux内核经典的双向链表。

          往后,我们会看到这两个链表各自是怎么串的,串的是什么内容。而在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;//4
	write_unlock(&file_systems_lock);
	return res;
}
           1、如果文件系统的next字段不为NULL,则说明不是新的文件系统类型,因此返回失败。
如果文件系统已经注册了,那么无法在注册了。每种类型的文件系统只能注册一次,但是可以有多种设备使用同一个类型的文件系统,也可以将同一类型的文件系统              挂载在不同的路径下。

           2、初始化fs->fs_supers;

           3、查找已经注册过的文件系统,查看准备要注册的文件系统是否已经注册过了,如果注册过,则返回错误。

           4、如果没有注册过,则将新的文件系统type添加文件系统列表中。

           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不为空,如果找不到,则返回next,并且next为空指针。后续会将新的文件系统类型添加在这里。

           







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值