文件系统注册

来源:互联网 发布:无名智者云签到源码 编辑:程序博客网 时间:2024/05/21 11:35

前面主要把VFS对象,以及他们如何串联起来的内容介绍得差不多了。相信走大现在,大家对大概的VFS工作机制有了相应的了解,接下来要做的事,就是把那些重要的细节描述清楚。首先,Linux内核支持很多不同的文件系统类型。本篇博文,我们将讨论文件系统注册——也就是通常在系统初始化期间并且在使用文件系统类型之前必须执行的基本操作。一旦文件系统被注册,其特定的那些虚拟文件模型中的对象中的函数对内核就是可用的了,因此文件系统类型可以安装在系统的目录树上。

 

接下来,我们再介绍一些特殊的文件系统类型,它们在Linux内核的内部设计中具有非常重要的作用。

 

1 文件系统类型注册

 

通常,用户在为自己的系统编译内核时可以把Linux配置为能够识别所有需要的文件系统。但是,文件系统的源代码实际上要么包含在内核映像中,要么作为一个模块被动态装入。

 

VFS必须对代码目前已在内核中的所有文件系统的类型进行跟踪。这就是通过进行文件系统类型注册来实现的。

 

每个注册的文件系统都用一个类型为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;
};

 

所有文件系统类型的对象都插入到一个单向链表中。由变量file_systems指向链表的第一个元素,而结构中的next字段指向链表的下一个元素:
static struct file_system_type *file_systems;

 

fs_supers字段表示给定类型的已安装文件系统所对应的超级块链表的头(第一个伪元素)。链表元素的向后和向前链接存放在超级块对象的s_instances字段中。get_sb字段指向依赖于文件系统类型的函数,该函数分配一个新的超级块对象并初始化它(如果需要,可读磁盘,我们在上一篇博文“把Linux中的VFS对象串联起来”有提到)。而kill_sb字段指向删除超级块的函数。

 

fs_flags字段存放如下几个标志:
FS_REQUIRES_DEV:这种类型的任何文件系统必须位于物理磁盘设备上
FS_BINARY_MOUNTDATA:文件系统使用的二进制安装数据
FS_REVAL_DOT:始终在目录项高速缓存中使“.”和“..”路径重新生效(针对网络文件系统)
FS_ODD_RENAME:“重命名”操作就是“移动”

 

在系统初始化期间,调用register_filesystem()函数来注册b编译时指定的b每个文件系统(通过find_filesystem()函数找到name);该函数把相应的file_system_type对象插入到文件系统类型的链表中:


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;
}

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;
}

 

另外,当实现文件系统的模块被装入时,也要调用register_filesystem()函数。在这种情况下,当该模块被卸载时,对应的文件系统也可以被注销(调用unregister_filesystem()函数)。

 

get_fs_type()函数(接收文件系统名作为它的参数)扫描已注册的文件系统链表以查找文件系统类型的name字段,并返回指向相应的file_system_type对象(如果存在)的指针:
struct file_system_type *get_fs_type(const char *name)
{
 struct file_system_type *fs;

 read_lock(&file_systems_lock);
 fs = *(find_filesystem(name));
 if (fs && !try_module_get(fs->owner))
  fs = NULL;
 read_unlock(&file_systems_lock);
 if (!fs && (request_module("%s", name) == 0)) {
  read_lock(&file_systems_lock);
  fs = *(find_filesystem(name));
  if (fs && !try_module_get(fs->owner))
   fs = NULL;
  read_unlock(&file_systems_lock);
 }
 return fs;
}

 

2 特殊文件系统

 

磁盘和网络文件系统能够使用户处理存放内核之外的信息,而特殊文件系统可以为系统序员和管理员提供一种容易的方式来操作内核的数据结构并实现操作系统的特殊特征。我们先列出Linux中所用的最常用的特殊文件系统;对于其中的每个文件系统,破折号隔出了它的安装点和简短描述:


bdev——none——块设备
binfmt_misc——any——其他可执行格式
devpts——/dev/pts——伪终端支持(开放组织的Unix98标准)
eventpollfs——none——由有效事件轮询机制使用
futexfs——none——由futex(快速用户空间加锁)机制使用
pipefs——none——管道
proc——/proc——对内核数据结构的常规访问点
rootfs——none——为启动阶段提供一个空的根目录
shm——none——IPC共享线性区
mqueue——any——实现POSIX消息队列时使用
sockfs——none——套接字
sysfs——/sys——对系统数据的常规访问点(一般是些驱动)
tmpfs——any——临时文件(如果不被交换出去就保持在RAM中)
usbfs——/proc/bus/usb——USB设备

 

注意,有几个文件系统没有固定的安装点(两个破折号之间的“any”)。这些文件系统可以由用户自由地安装和使用。此外,一些特殊文件系统根本没有安装点(两个破折号之间的“none”)。它们不是用于与用户交互,但是内核可以用它们来很容易地重新使用VFS层的某些代码。例如,有了pipefs特殊文件系统,就可以把管道和FIFO文件以相同的方式对待。

 

特殊文件系统不限于物理块设备。然而,内核给每个安装的特殊文件系统分配一个虚拟的块设备,让其主设备号为0而次设备号具有任意值(每个特殊文件系统有不同的值)。

set_anon_super()函数用于初始化特殊文件系统的超级块;该函数本质上获得一个未使用的次设备号dev,然后用主设备号0和次设备号dev设置新超级块的s_dev字段。而另一个kill_anon_super()函数移走特殊文件系统的超级块。unnamed_dev_idr变量包含指向一个辅助结构(记录当前在用的次设备号)的指针。尽管有些内核设计者不喜欢虚拟块设备标识符,但是这些标识符有助于内核以统一的方式处理特殊文件系统和普通文件系统。