当前位置:文档之家› 计算机操作系统教程(第四版)PPT课件:第10章 Linux文件系统

计算机操作系统教程(第四版)PPT课件:第10章 Linux文件系统

的操作。
为了帮助读者更好地理解这一过程,笔者用一个具体的例子 来说明:我们准备将来自主硬盘第 2 分区(hda2)上的 ext2 文件 系统安装到前面创建的 "/dev" 目录中。那么对于 sys_mount()
函数的调用便具体为:
sys_mount(“hda2”,“/dev ”,“ext2”,…);
3 中 "/" 目录对应的 dentry 结构中,由链表实现这一关系。接下来会再分配一个 struct inode 结构。Inode 中的 i_sb 和 dentry 中的 d_sb 分别都指向图 3 中的 sb,这
样看来,在同一文件系统下建立新的目录时并不需要重新分配一个超级块结构, 因为毕竟它们都属于同一文件系统,因此一个文件系统只对应一个超级块。
# mount -t msdos /dev/fd0 /mnt/floppy
# mount -t iso9660 /dev/cdrom /mnt/cdrom 现在就可以进入/mnt/winc等目录读写这些文件系统了。
描述在 VFS 的目录树中向其中某个目录(安装点 mount point)上挂载(mount)一 个文件系统的过程。
第10章 Linux文件系统
10.1Linux文件系统的特点与文件类别 10.1.1 特点
10.1.2文件类型
10.2Linux的虚拟文件系统 10.2.1 虚拟文件系统VFS框架
进程管理、内存管理子系统
MINIX
VFS EXT2
MSDOS
VFS 是一种软件机制,也许称它为 Linux 的文件系统管理者更确切点,与它相关 的数据结构只存在于物理内存当中。所以在每次系统初始化期间,Linux 都首先 要在内存当中构造一棵 VFS 的目录树(在 Linux 的源代码里称之为 namespace),实 际上便是在内存中建立相应的数据结构。VFS 目录树在 Linux 的文件系统模块中 是个很重要的概念,希望读者不要将其与实际文件系统目录树混淆,VFS 中的各 目录其主要用途是用来提供实际文件系统的挂载点,当然在 VFS 中也会涉及到文
件级的操作,本文不阐述这种情况。一种可能的目录树在内存中的影像:
10.2.2 Linux虚拟文件系统的数据结构 1. VFS的超级块 super_block
2. 索引节点 inode
3. 文件 file
4. 目录项dentry
10.2.3VFS的系统调用
10.3文件系统的注册和挂装
录 (struct dentry)dentry,并将 dentry 中的 d_sb 指针指向 sb, d_inode 指针指向 inode。
6) 将 mnt 中的 mnt_sb 指针指向 sb,mnt_root 和 mnt_mountpoint 指针指向 dentry,而 mnt_parent指针则指向自
读者可在图 3 的基础上参看图 4)。
需要强调一点的是,既然 rootfs 文件系统被 mount 到了 VFS 树上,那么它在 sys_mkdir 的过程中必然会参与进来,事实上
在整个过程中,rootfs 文件系统中的 ramfs_mkdir、 ramfs_lookup 等函数都曾被调用过。
10.3.4挂装一般文件系统
这样,当调用 sys_mkdir 成功地在 VFS 的目录树中新建立一 个目录 "/dev" 之后,在图 3 的基础上,新的数据结构之间的 关系便如图 4 所示。图 4 中颜色较深的两个矩形块 new_inode 和 new_entry 便是在sys_mkdir() 函数中新分配的内存结构,至 于图中的 mnt,sb,dentry,inode 等结构,仍为图 3 中相应的数据 结构,其相互之间的链接关系不变(图中为避免过多的链接曲 线,忽略了一些链接关系,如 mnt 和 sb,dentry之间的链接,
身。
这样,当 do_kern_mount() 函数返回时,以上分配出来的各数 据结构和 rootfs 文件系统的关系将如上图 3 所示。
VFS 下目录的建立
为了更好地理解 VFS,下面我们用一个实际例子来看看 Linux 是 如何在 VFS 的根目录下建立一个新的目录 "/dev" 的。
要在 VFS 中建立一个新的目录,首先我们得对该目录进行搜索, 搜索的目的是找到将要建立的目录其父目录的相关信息,因为" 皮之不存,毛将焉附"。比如要建立目录 /home/ricard,那么首先 必须沿目录路径进行逐层搜索,本例中先从根目录找起,然后在 根目录下找到目录 home,然后再往下,便是要新建的目录名
在这个场景里,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() 函数,
ricard,那么前面讲得要先对目录搜索,在该例中便是要找到 ricard 这个新目录的父目录,也就是 home 目录所对应的信息。
当然,如果搜索的过程中发现错误,比如要建目录的父目录并不 存在,或者当前进程并无相应的权限等等,这种情况系统必然会
调用相关过程进行处理,对于此种情况,本文略过不提。

这里的大体过程是:新分配了一个 struct dentry 结构的内存空间, 用于记录 dev 目录所对应的信息,该dentry 结构将会挂接到其父目录中,也就是图
统则是 VFS 存在的基础。一般文件系统的注册都是通过 module_init 宏以及 do_initcalls() 函数来完成(读者可通过阅读 module_init 宏的声明及 arch\i386\vmlinux.lds 文件来理解这一 过程),但是 rootfs 的注册却是通过 init_rootfs() 这一初始化函 数来完成,这意味着 rootfs 的注册过程是 Linux 内核初始化阶
10.3.1文件系统注册
这里的文件系统是指可能会被挂载到目录树中的各个实际文件系统,所谓实际文 件系统,即是指VFS 中的实际操作最终要通过它们来完成而已,并不意味着它们
一定要存在于某种特定的存储设备上。比如在笔者的 Linux 机器下就注册有 “rootfs”、“proc”、“ext2”、“sockfs” 等十几种文件系统。
段不可分割的一部分。
init_rootfs() 通过调用 register_filesystem(&rootfs_fs_type) 函数 来完成 rootfs 文件系统注册的,其中rootfs_fs_type 定义如下:
VFS 目录树的建立
既然是树,所以根是其赖以存在的基础,本节阐述 Linux 在初始化阶段是如何建立根结点 的,即 "/"目录。这其中会包括挂载 rootfs 文件系统到根目录 "/" 的具体过程。构造根目录
参见图2.
4) ramfs_read_super() 函数调用 ramfs_get_inode() 在内存中 分配了一个 inode 结构 (struct inode) inode,并初始化其部
分成员变量,其中比较重要的有 i_op、i_fop 和 i_sb:
5) ramfs_read_super() 函数在分配和初始化了 inode 结构之后, 会调用 d_alloc_root() 函数来为 VFS的目录树建立起关键的根目
这一过程可简单描述为:将某一设备(dev_name)上某一文件系统 (file_system_type)安装到VFS目录树上的某一安装点(dir_name)。它要解决的问 题是:将对 VFS 目录树中某一目录的操作转化为具体安装到其上的实际文件
系统的对应操作。
比如说,如果将 hda2 上的根文件系统(假设文件系统类型为 ext2)安 装到了前一节中新建立的 "/dev" 目录上(此时,"/dev" 目录就成为了 安装点),那么安装成功之后应达到这样的目的,即:对 VFS 文件 系统的 "/dev" 目录执行 "ls" 指令,该条指令应能列出 hda2 上 ext2 文件系统的根目录下所有的目录和文件。很显然,这里的关键是如 何将对 VFS 树中 "/dev" 的目录操作指令转化为安装在其上的 ext2 这一实际文件系统中的相应指令。所以,接下来的叙述将抓住如何 转化这一核心问题。在叙述之前,读者不妨自己设想一下 Linux 系 统会如何解决这一问题。记住:对目录或文件的操作将最终由目录 或文件所对应的 inode 结构中的 i_op 和 i_fop 所指向的函数表中对 应的函数来执行。所以,不管最终解决方案如何,都可以设想必然 要通过将对 "/dev" 目录所对应的 inode 中 i_op 和 i_fop 的调用转换 到 hda2 上根文件系统 ext2 中根目录所对应的 inode 中 i_op 和 i_fop
所谓的安装系统链表。
在把这些函数调用后形成的数据结构关系理清楚之后,让我们回到本章节开始提到 的问题,即将 ext2 文件系统安装到了 "/dev " 上之后,对该目录上的操作如何转化为 对 ext2 文件系统相应的操作。从图 5上看到,对 sys_mount() 函数的调用并没有直接 改变 "/dev " 目录所对应的 inode (即图中的 new_inode变量)结构中的 i_op 和 i_fop 指 针,而且 "/dev " 所对应的 dentry(即图中的 new_dentry 变量)结构仍然在 VFS 的目录 树中,并没有被从其中隐藏起来,相应地,来自 hda2 上的 ext2 文件系统的根目录
相关主题