Chinaunix首页 | 论坛 | 博客
  • 博客访问: 237065
  • 博文数量: 61
  • 博客积分: 125
  • 博客等级: 入伍新兵
  • 技术积分: 100
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-23 23:28
文章分类

全部博文(61)

文章存档

2014年(37)

2013年(21)

2012年(3)

分类: LINUX

2013-06-20 19:15:08

原文地址:文件系统的注册 作者:1234567lq

一、概述
   当内核被编译时,就已经确定了可以支持哪些文件系统,这些文件系统在系统引导时,在
 VFS 中进行注册。如果文件系统是作为内核可装载的模块,则在实际安装时进行注册,并在模块卸载时注销。每个文件系统都有一个初始化例程(比如对于ext2文件系统中就有一个函数为init_ext2_fs的函数来负责文件系统的注册),它的作用就是在 VFS 中进行注册,即填写一个叫做file_system_type的数据结构(文件系统的注册其实实质就是填写file_system_type类型,并把文件系统挂载到file_systems这个链表中),该结构包含了文件系统的名称以及一个指向对应的 VFS 超级块读取例程的地址,所有已注册的文件系统的file_system_type结构形成一个链表,为区别后面将要说到的已安装的文件系统形成的另一个链表,我们把这个链表称为注册链表。如下图示就是内核中的 file_system_type 链表,链表头由 file_systems 变量指定。

                               已经注册的文件系统在内存中形成的链表
二、文件注册的关键数据结构file_system_type的介绍(以下的内容都是针对的是内核版本为2.6.32的代码而言的,最新的内核版本的file_system_type结构是不一样的,这个类型主要是用在文件系统的挂载mount的时候)
file_system_type结构的各个字段如下

点击(此处)折叠或打开

  1. struct file_system_type {
  2.         const char *name;
  3.         int fs_flags;
  4.         int (*get_sb) (struct file_system_type *, int,
  5.                        const char *, void *, struct vfsmount *);
  6.         void (*kill_sb) (struct super_block *);
  7.         struct module *owner;
  8.         struct file_system_type * next;
  9.         struct list_head fs_supers;
  10. 
  11.         struct lock_class_key s_lock_key;
  12.         struct lock_class_key s_umount_key;
  13. 
  14.         struct lock_class_key i_lock_key;
  15.         struct lock_class_key i_mutex_key;
  16.         struct lock_class_key i_mutex_dir_key;
  17.         struct lock_class_key i_alloc_sem_key;
  18. };
各个字段的含义如下:
.name字段:文件系统的名字。这个是一个字符串的类型。比如“ext2”、“ext3”等等就是赋值给该字段
.fs_flags字段:该字段主要是指明具体文件系统的一些特性,有关标志位的定义在fs.h中,这里贴出如下:

点击(此处)折叠或打开

  1. /* public flags for file_system_type */
  2.     #define FS_REQUIRES_DEV 1
  3. #define FS_NO_DCACHE 2 /* Only dcache the necessary things. */
  4.     #define FS_NO_PRELIM 4 /* prevent preloading of dentries, even if
  5.                             * FS_NO_DCACHE is not set.
  6.                            */
  7. #define FS_SINGLE 8 /* Filesystem that can have only one superblock */
  8. #define FS_NOMOUNT 16 /* Never mount from userland */
  9. #define FS_LITTER 32 /* Keeps the tree in dcache */
  10. #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
  11.                                   * as nfs_rename() will be cleaned up
  12.                                    */
对某些常用标志的说明如下:
(1)有些虚拟的文件系统,如pipe、共享内存等,根本不允许由用户进程通过系统调用mount()来安装。这样的文件系统其fs_flags中的FS_NOMOUNT标志位为1。
(2)一般的文件系统类型要求有物理的设备作为其物质基础,其fs_flags中的FS_REQUIRES_DEV标志位为1,这些文件系统如Ext2、Minix、ufs等。
(3)有些虚拟文件系统在安装了同类型中的第一个“设备”,从而创建了其超级块的super_block数据结构,在安装同一类型中的其他设备时就共享已存在的super_block结构,而不再有自己的超级块结构。此时fs_flags中的FS_SINGLE标志位为1,表示整个文件系统只有一个超级块,而不像一般的文件系统类型那样,每个具体的设备上都有一个超级块。
.get_sb字段:这个函数将在kern_mount函数中调用,用于获得文件系统(分区)的超级块(super_block)的信息,并将这个填充到vfsmount的mnt_sb成员中。这个在文件系统mount的过程中能用到。
.owner字段如果file_system_type所代表的文件系统是通过可安装模块实现的,则该指针指向代表着具体模块的module结构。如果文件系统是静态地链接到内核,则这个域为NULL。实际上,你只需要把这个域置为THIS_MODLUE (这是个一个宏),它就能自动地完成上述工作。
.next字段:
把所有的file_system_type结构链接成单项链表的链接指针,变量file_systems指向这个链表。这个链表是一个临界资源,受file_systems_lock自旋读写锁的保护。
.fs_supers字段:
这个域是Linux2.4.10以后的内核版本中新增加的,这是一个双向链表。链表中的元素是超级块结构。如前说述,每个文件系统都有一个超级块,但有些文件系统可能被安装在不同的设备上,而且每个具体的设备都有一个超级块,这些超级块就形成一个双向链表即该字段就是连接安装同一个文件系统的不同超级块。(注:在安装文件系统的时候,创建了相应的超级块对象之后,会把该超级块对象插入到两个链表中,一个是所有超级块对象形成的一个链表,另一个就是同一个文件系统对应的双向链表,即文件系统的fs_supers字段对应的双向链表)。
三、文件系统的注册函数

点击(此处)折叠或打开

  1. static int __init init_ext2_fs(void)
  2. {
  3.         int err = init_ext2_xattr();
  4.         if (err)
  5.                 return err;
  6.         err = init_inodecache();
  7.         if (err)
  8.                 goto out1;
  9.         err = register_filesystem(&ext2_fs_type);
  10.         if (err)
  11.  goto out;
  12.  return 0;
  13. out:
  14.         destroy_inodecache();
  15. out1:
  16.  exit_ext2_xattr();
  17.         return err;
  18. }
如上是ext2文件系统的初始化函数,其中最主要的函数就是register_filesystem()函数。该函数就是完成文件系统的注册功能。其中传入的参数为ext2_fs_type,该参数在文件fs/ext2/super.c中的声明如下:

点击(此处)折叠或打开

  1. static struct file_system_type ext2_fs_type = {
  2.         .owner = THIS_MODULE,
  3.         .name = "ext2",
  4.         .get_sb = ext2_get_sb,
  5.         .kill_sb = kill_block_super,
  6.         .fs_flags = FS_REQUIRES_DEV,
  7. }
这个主要是定义了一个file_system_type的一个变量并且填充这个变量中的各个字段。这里主要涉及到的两个函数ext2_get_sb()函数(该函数主要是获取超级块的信息)和kill_block_super()函数,这两个函数在下面会进行详细的讲解。
下面我们接着看register_filesystem()函数,该函数在文件fs/filesystems.c文件中实现,具体的内核代码如下:

点击(此处)折叠或打开

  1. int register_filesystem(struct file_system_type * fs)
  2.  {
  3.           int res = 0;
  4.          struct file_system_type ** p;
  5.   
  6.          BUG_ON(strchr(fs->name, '.'));//用来判断内核是不是出现问题,其实实质就是相当于assert()函数,也就是文件系统名不能以.开始
  7.          if (fs->next)//如果fs的next不为空,说明这个文件系统已经注册了,这个时候就不需要在进行注册了
  8.                   return -EBUSY;
  9.           INIT_LIST_HEAD(&fs->fs_supers);
  10.           write_lock(&file_systems_lock);//由于file_systems链表的操作必须是互斥进行的,所以必须要加锁
  11.           p = find_filesystem(fs->name, strlen(fs->name));//该函数主要是在fs_systems这个链表中寻找该文件系统,如果寻找到了则返回相应的p指针指向该文件系统的地址,如果没有找到则p=NULL,并返回,显然第一次注册返回的p肯定是NULL的。
  12.           if (*p)
  13.                   res = -EBUSY;
  14.           else
  15.                   *p = fs;//把fs插入到file_systems链表中。
  16.           write_unlock(&file_systems_lock);//解锁
  17.           return res;
  18.   }
四、文件系统的取消
   文件系统的取消主要的功能就是把该文件系统对应的file_system_type对象从file_systems的链表中删除具体的代码如下:

点击(此处)折叠或打开

  1. int unregister_filesystem(struct file_system_type * fs)
  2.  {
  3.         struct file_system_type ** tmp;
  4.  
  5.  write_lock(&file_systems_lock);
  6.          tmp = &file_systems;
  7.   while (*tmp) {
  8.                  if (fs == *tmp) {
  9.   *tmp = fs->next;
  10.   fs->next = NULL;
  11.   write_unlock(&file_systems_lock);
  12.                          return 0;
  13.                 }
  14.   tmp = &(*tmp)->next;
  15.   }
  16.   write_unlock(&file_systems_lock);
  17.         return -EINVAL;
  18.  }
上面的代码很简单,在这里就不详细的说明了。

五、总结
   对于register_filesystem即注册文件系统其实实质就是把file_system_type的对象插入到file_systems的链表中。同时要实现相应的get_sb()函数(该函数是获取该文件系统的超级块的信息)







阅读(926) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~