没有合适的资源?快使用搜索试试~ 我知道了~
首页解析Linux的VFS机制
解析Linux的VFS机制。本文阐述 Linux 中的文件系统部分,源代码来自基于 IA32 的 2.4.20 内核。总体上说 Linux 下的文件系统主要可分为三大块:一是上层的文件系统的系统调用,二是虚拟文件系统 VFS(Virtual Filesystem Switch),三是挂载到 VFS 中的各实际文件系统,例如 ext2,jffs 等。本文侧重于通过具体的代码分析来解释 Linux 内核中 VFS 的内在机制,在这过程中会涉及到上层文件系统调用和下层实际文件系统的如何挂载。文章试图从一个比较高的角度来解释 Linux 下的 VFS 文件系统机制。
资源详情
资源评论
资源推荐

解析 Linux 中的 VFS 文件系统机制
级别: 初级
Ricard Chen (ricard_chen@yahoo.com)
2005 年 4 月 01 日
本文阐述 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 目录树结构

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 链表结构
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)。
在这个场景里,do_kern_mount() 做的工作主要是:
1 )调用 alloc_vfsmnt() 函数在内存 里 申 请 了 一 块 该类型的内存 空间( struct vfsmount
*mnt),并初始化其部分成员变量。
2) 调用 get_sb_nodev() 函数在内存中分配一个超级块结构 (struct super_block) sb,并初
始化其部分成员变量,将成员 s_instances 插入到 rootfs 文件系统类型结构中的 fs_supers 指
向的双向链表中。
3) 通过 rootfs 文件系统中的 read_super 函数指针调用 ramfs_read_super() 函数。还记得当初
注册 rootfs 文件系统时,其成员 read_super 指针指向了 ramfs_read_super() 函数,参见图 2.
4) ramfs_read_super() 函数调用 ramfs_get_inode() 在内存中分配了一个 inode 结构 (struct
inode) inode,并初始化其部分成员变量,其中比较重要的有 i_op、i_fop 和 i_sb:
inode->i_op = &ramfs_dir_inode_operations;
inode->i_fop = &dcache_dir_ops;
inode->i_sb = sb;
这使得将来通过文件系统调用对 VFS 发起的文件操作等指令将被 rootfs 文件系统中相应的
剩余12页未读,继续阅读


















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0