这是ibm上的一篇文章,写的很好!

级别: 高级

Ricard Chen

2005 年 4 月

本 文阐述 Linux 中的文档系统部分,源代码来自基于 IA32 的 2.4.20 内核。总体上说 Linux 下的文档系统主要可分为三大块:一是上层的文档系统的系统调用,二是虚拟文档系统 VFS(Virtual Filesystem Switch),三是挂载到 VFS 中的各实际文档系统,例如 ext2,jffs 等。本文侧重于通过具体的代码分析来解释 Linux 内核中 VFS 的内在机制,在这过程中会涉及到上层文档系统调用和下层实际文档系统的如何挂载。文章试图从一个比较高的角度来解释 Linux 下的 VFS 文档系统机制。

1. 摘要
本 文阐述 Linux 中的文档系统部分,源代码来自基于 IA32 的 2.4.20 内核。总体上说 Linux 下的文档系统主要可分为三大块:一是上层的文档系统的系统调用,二是虚拟文档系统 VFS(Virtual Filesystem Switch),三是挂载到 VFS 中的各实际文档系统,例如 ext2,jffs 等。本文侧重于通过具体的代码分析来解释 Linux 内核中 VFS 的内在机制,在这过程中会涉及到上层文档系统调用和下层实际文档系统的如何挂载。文章试图从一个比较高的角度来解释 Linux 下的 VFS 文档系统机制,所以在叙述中更侧重于整个模块的主脉络,而不拘泥于细节,同时配有若干张插图,以帮助读者理解。

相对来说,VFS 部分的代码比较繁琐复杂,希望读者在阅读完本文之后,能对 Linux 下的 VFS 整体运作机制有个清楚的理解。建议读者在阅读本文前,先尝试着自己阅读一下文档系统的源代码,以便建立起 Linux 下文档系统最基本的概念,比如至少应熟悉 super block, dentry, inode,vfsmount 等数据结构所表示的意义,这样再来阅读本文以便加深理解。

2. VFS 概述
VFS 是一种软件机制,也许称他为 Linux 的文档系统管理者更确切点,和他相关的数据结构只存在于物理内存当中。所以在每次系统初始化期间,Linux 都首先要在内存当中构造一棵 VFS 的目录树(在 Linux 的源代码里称之为 namespace),实际上便是在内存中建立相应的数据结构。VFS 目录树在 Linux 的文档系统模块中是个很重要的概念,希望读者不要将其和实际文档系统目录树混淆,在笔者看来,VFS 中的各目录其主要用途是用来提供实际文档系统的挂载点,当然在 VFS 中也会涉及到文档级的操作,本文不阐述这种情况。下文提到目录树或目录,假如不特别说明,均指 VFS 的目录树或目录。图 1 是一种可能的目录树在内存中的影像:

图 1:VFS 目录树结构
图 1:VFS 目录树结构

3. 文档系统的注册
这 里的文档系统是指可能会被挂载到目录树中的各个实际文档系统,所谓实际文档系统,即是指VFS 中的实际操作最终要通过他们来完成而已,并不意味着他们一定要存在于某种特定的存储设备上。比如在笔者的 Linux 机器下就注册有 "rootfs"、"proc"、"ext2"、"sockfs" 等十几种文档系统。

3.1 数据结构
在 Linux 源代码中,每种实际的文档系统用以下的数据结构表示:



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

注册过程实际上将表示各实际文档系统的 struct file_system_type 数据结构的实例化,然后形成一个链表,内核中用一个名为 file_systems 的全局变量来指向该链表的表头。

3.2 注册 rootfs 文档系统
在 众多的实际文档系统中,之所以单独介绍 rootfs 文档系统的注册过程,实在是因为该文档系统 VFS 的关系太过密切,假如说 ext2/ext3 是 Linux 的本土文档系统,那么 rootfs 文档系统则是 VFS 存在的基础。一般文档系统的注册都是通过 module_init 宏连同 do_initcalls() 函数来完成(读者可通过阅读module_init 宏的声明及 arch\i386\vmlinux.lds 文档来理解这一过程),但是 rootfs 的注册却是通过 init_rootfs() 这一初始化函数来完成,这意味着 rootfs 的注册过程是 Linux 内核初始化阶段不可分割的一部分。

init_rootfs() 通过调用 register_filesystem(&rootfs_fs_type) 函数来完成 rootfs 文档系统注册的,其中rootfs_fs_type 定义如下:



struct file_system_type rootfs_fs_type = { \
name: "rootfs", \
read_super: ramfs_read_super, \
fs_flags: FS_NOMOUNT|FS_LITTER, \
owner: THIS_MODULE, \
}

注册之后的 file_systems 链表结构如下图2所示:

图 2: file_systems 链表结构
图 2: file_systems 链表结构

4. VFS 目录树的建立
既 然是树,所以根是其赖以存在的基础,本节阐述 Linux 在初始化阶段是如何建立根结点的,即 "/"目录。这其中会包括挂载 rootfs 文档系统到根目录 "/" 的具体过程。构造根目录的代码是在 init_mount_tree() 函数 (fs\namespace.c) 中。

首 先,init_mount_tree() 函数会调用 do_kern_mount("rootfs", 0, "rootfs", NULL) 来挂载前面已注册了的 rootfs 文档系统。这看起来似乎有点奇怪,因为根据前面的说法,似乎是应该先有挂载目录,然后再在其上挂载相应的文档系统,然而此时 VFS 似乎并没有建立其根目录。没关系,这是因为这里我们调用的是 do_kern_mount(),这个函数内部自然会创建我们最关心也是最关键的根目录(在 Linux 中,目录对应的数据结构是 struct dentry)。

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!