正在加载
请稍等

菜单

红楼飞雪 梦

15526773247

文章

Home 文件系统的注册
Home 文件系统的注册

文件系统的注册

未分类 by

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

仅示意性地说明系统中已安装的三个文件系统Ext2、proc、iso9660其file_system_type结构所形成的链表。当然,系统中实际安装的文件系统要更多。

file_system_type的数据结构在fs.h中定义如下:

struct file_system_type
{
    const char *name;
    int fs_flags;
    struct super_block *(*read_super) (struct super_block *, void *, int);
    struct module *owner;
    struct file_system_type * next;
    struct list_head fs_supers;
};

对其中几个域的说明如下:

  • name:文件系统的类型名,以字符串的形式出现。
  • fs_flags:指明具体文件系统的一些特性,有关标志定义于h中:
/* public flags for file_system_type */
#define FS_REQUIRES_DEV 1
#define FS_NO_DCACHE    2 /* Only dcache the necessary things. */
#define FS_NO_PRELIM    4 /* prevent preloading of dentries, even if* FS_NO_DCACHE is not set.*/
#define FS_SINGLE       8 /* Filesystem that can have only one superblock */
#define FS_NOMOUNT      16 /* Never mount from userland */
#define FS_LITTER       32 /* Keeps the tree in dcache */
#define FS_ODD_RENAME   32768   /* Temporary stuff; will go away as soon* as nfs_rename() will be cleaned up*/

对某些常用标志的说明如下:

  • 有些虚拟的文件系统,如pipe、共享内存等,根本不允许由用户进程通过系统调用mount()来安装。这样的文件系统其fs_flags中的FS_NOMOUNT标志位为1。
  • 一般的文件系统类型要求有物理的设备作为其物质基础,其fs_flags中的FS_REQUIRES_DEV标志位为1,这些文件系统如Ext2、Minix、ufs等。
  • 有 些虚拟文件系统在安装了同类型中的第一个“设备”,从而创建了其超级块的super_block数据结构,在安装同一类型中的其他设备时就共享已存在的 super_block结构,而不再有自己的超级块结构。此时fs_flags中的FS_SINGLE标志位为1,表示整个文件系统只有一个超级块,而不 像一般的文件系统类型那样,每个具体的设备上都有一个超级块。
  • read_super:这是各种文件系统读入其超级块的函数指针。因为不同的文件系统其超级块不同,因此其读入函数也不同。
  • owner: 如果file_system_type所代表的文件系统是通过可安装模块实现的,则该指针指向代表着具体模块的module结构。如果文件系统是静态地链 接到内核,则这个域为NULL。实际上,你只需要把这个域置为THIS_MODLUE (这是个一个宏),它就能自动地完成上述工作。
  • next:把所有的file_system_type结构链接成单项链表的链接指针,变量file_systems指向这个链表。这个链表是一个临界资源,受file_systems_lock自旋读写锁的保护。
  • fs_supers: 这个域是Linux4.10以后的内核版本中新增加的,这是一个双向链表。链表中的元素是超级块结构。如前说述,每个文件系统都有一个超级块,但有些文件 系统可能被安装在不同的设备上,而且每个具体的设备都有一个超级块,这些超级块就形成一个双向链表。

搞清楚这个数据结构的各个域以后,就很容易理解下面的注册函数register_filesystem(),该函数定义于fs/super.c:

/**
*      register_filesystem - register a new filesystem
*      @fs:
the file system structure
*
*      Adds the file system passed to the list of file systems the kernel
*      is aware of for mount and other syscalls. Returns 0 on success,
*      or a negative errno code on an error.
*
*      The &struct file_system_type that is passed is linked into the kernel
        *      structures and must not be freed until the file system has been
        *      unregistered.
        */
int register_filesystem(struct file_system_type * fs)
{
    int res = 0;
    struct file_system_type ** p;
    if (!fs)
        return -EINVAL;
    if (fs->next)
        return -EBUSY;
    INIT_LIST_HEAD(&fs->fs_supers);
    write_lock(&file_systems_lock);
    p = find_filesystem(fs->name);
    if (*p)
        res = -EBUSY;
    else
        *p = fs;
    write_unlock(&file_systems_lock);
    return res;
}

find_filesystem()函数在同一个文件中定义如下:

static struct file_system_type **find_filesystem(const char *name)
{
    struct file_system_type **p;
    for (p=&file_systems; *p; p=&(*p)->next)
        if (strcmp((*p)->name,name) == 0)
            break;
    return p;
}

注意,对注册链表的操作必须互斥地进行,因此,对该链表的查找加了写锁write_lock。

文 件系统注册后,还可以撤消这个注册,即从注册链表中删除一个file_system_type 结构,此后系统不再支持该种文件系统。fs/super.c中的unregister_filesystem()函数就是起这个作用的,它在执行成功后返 回0,如果注册链表中本来就没有指定的要删除的结构,则返回-1,其代码如下:

/**
*      unregister_filesystem - unregister a file system
*      @fs: filesystem to unregister
*
*      Remove a file system that was previously successfully registered
*      with the kernel. An error is returned if the file system is not found.
*      Zero is returned on a success.
*
*      Once this function has returned the &struct file_system_type structure
*      may be freed or reused.
*/
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);
            return 0;
        }
        tmp = &(*tmp)->next;
    }
    write_unlock(&file_systems_lock);
    return -EINVAL;
}

 

22 2015-11

 

我要 分享

 

 

本文 作者

 

相关 文章