Download presentation
Presentation is loading. Please wait.
1
中国科学技术大学计算机系 陈香兰(0551-3606864) xlanchen@ustc.edu.cn Spring 2009
Linux内核源代码导读 中国科学技术大学计算机系 陈香兰(0551- ) Spring 2009
2
Linux的虚拟文件系统
3
提纲 虚拟文件系统VFS的作用 VFS的数据结构 文件系统类型 文件系统安装 路径名查找 VFS系统调用的实现 文件加锁 2019/1/2
Linux操作系统源代码导读
4
虚拟文件系统VFS的作用 虚拟文件系统 Linux与其他类Unix系统一样,采用虚拟文件系统VFS来达到支持多种文件系统格式的目标
Virtual Filesystem Virtual Filesystem Switch VFS是一个软件层,用来处理与Unix标准文件系统相关的所有系统调用。 是用户应用程序与文件系统实现之间的抽象层 能为各种文件系统提供一个通用的、统一的接口 Linux与其他类Unix系统一样,采用虚拟文件系统VFS来达到支持多种文件系统格式的目标 2019/1/2 Linux操作系统源代码导读
5
VFS在一个简单文件复制操作中的作用 假设用户输入以下shell命令 其中,
$ cp /floppy/TEST /tmp/test 其中, /floppy是MS-DOS的磁盘的一个挂载点(安装点) /tmp是Ext2文件系统中的一个目录 对于cp命令而言,它不需要知道/floppy/TEST和/tmp/test分别是什么文件系统类型 在cp命令中,它通过VFS提供的系统调用接口进行文件操作 2019/1/2 Linux操作系统源代码导读
6
2019/1/2 Linux操作系统源代码导读
7
VFS支持的文件系统类型 VFS支持的文件系统可以划分为三种主要类型 基于磁盘的文件系统:它们管理在本地磁盘分区中可用的存储空间
Linux使用的文件系统:ext2、ext3、ReiserFS Unix家族的文件系统:SYSV文件系统,UFS,MINIX文件系统以及VERITAS VxFS 微软公司的文件系统:MS-DOS、VFAT以及NTFS ISO9660CD-ROM文件系统和通用磁盘格式的DVD文件系统 其他有专利权的文件系统,如HPFS、HFS、AFFS、ADFS 起源于非Linux系统的其他日志文件系统,JFS,XFS 2019/1/2 Linux操作系统源代码导读
8
各种不同的文件系统通过mount(挂载、安装)到根文件系统中
网络文件系统:用于访问属于其他网络计算机的文件系统所包含的文件 NFS、Coda、AFS、SMB、NCP 特殊文件系统 不同于上述两大类 不管理具体的磁盘空间 /proc 各种不同的文件系统通过mount(挂载、安装)到根文件系统中 在Linux中,根文件系统即根目录所代表的文件系统 通常是ext2文件系统 2019/1/2 Linux操作系统源代码导读
9
VFS中通用文件模型概念 VFS的基本思想:引入一个通用文件模型,这个模型能够表示所有支持的文件系统
对于一个具体实现的文件系统,在处理时,需要将其进行概念上的转换 例如,在通用文件模型中,目录被看成是普通文件 在实现上, read()sys_readfile数据结构f_opMS_DOS文件操作指针(其中的read操作) 类似面向对象的概念 2019/1/2 Linux操作系统源代码导读
10
sys_read(unsigned int fd, char __user * buf, size_t count)
vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) file->f_op->read(file, buf, count, pos); 例如:字符设备:filp->f_op = fops_get(p->ops); 2019/1/2 Linux操作系统源代码导读
11
通用文件模型有下列对象类型组成 超级块对象(superblock object) 索引节点对象(inode object)
存放文件系统相关信息:例如文件系统控制块 索引节点对象(inode object) 存放具体文件的一般信息:文件控制块/inode 文件对象(file object) 存放已打开的文件和进程之间交互的信息 目录项对象(dentry object) 存放目录项与文件的链接信息 2019/1/2 Linux操作系统源代码导读
12
三个不同的进程打开同一个文件 同一个 硬链接 两个不同的硬链接 2019/1/2 Linux操作系统源代码导读
13
VFS所处理的系统调用 mount、umount:挂载/卸载文件系统 sysfs :获取文件系统信息
statfs、fstatfs、ustat :获取文件系统统计信息 chroot :更改根目录 chdir、fchdir、getcwd :操纵当前工作目录 mkdir、rmdir :创建/删除目录 getdents、readdir 、link 、unlink 、rename :对目录项进行操作 readlink 、symlink :对符号链接进行操作 chown 、fchown 、lchown :更改文件所有者 chmod 、fchmod 、utime :更改文件属性 open、close、create … 2019/1/2 Linux操作系统源代码导读
14
上述大部分操作之需要与通用文件模型中的一些对象打交道,而不需要真正操作具体的文件系统和文件,因此可以把VFS看成是一个“通用”的文件系统,在必要时依赖某种具体的文件系统
2019/1/2 Linux操作系统源代码导读
15
VFS的数据结构 每个VFS对象都对应一定的数据结构,在这个数据结构中包含对象的属性及其方法
一个具体的文件系统:超级块对象:super_block 所有超级块链表:super_blocks :s_list域 文件系统特有信息:s_fs_info域 脏标志:s_dirt域 文件系统特有方法:super_operations数据结构及域 2019/1/2 Linux操作系统源代码导读
16
一个具体的文件:Inode对象:inode
一个打开文件:文件对象:file 文件操作指针f_pos 文件对象特有的方法 专用高速缓存:flip,filp_cachep 目录项对象:dentry 2019/1/2 Linux操作系统源代码导读
17
与进程相关的文件 文件系统相关信息fs_struct 打开文件相关信息files_struct 2019/1/2
count:共享此表的进程的个数 Root:根目录的目录项及在该目录上安装的文件系统对象 Pwd:当前工作目录的目录项及在该目录上安装的文件系统对象 2019/1/2 Linux操作系统源代码导读
18
2019/1/2 Linux操作系统源代码导读 Count:共享本数据结构的进程的个数
Max_fds:文件对象的当前最大数目;参见alloc_fdtable Next_fd:初始化为0;分配fd的时候,被赋值为所分配的最大文件描述符加1; Fd:指向文件对象指针数组;通常指向fd_array,当fd_array不够时,将分配一个新的更大的文件对象指针数组,将其地址存放在fd字段中,并同时更新max_fds字段的值。 Close_on_exec:指向执行exec时需要关闭的文件描述符的指针 Open_fds:指向打开文件描述符的指针 Close_on_exec_init:执行exec时需要关闭的文件描述符的初始集合 Open_fds_init:文件描述符的初始集合 Fd_array:文件对象指针的初始化数组 2019/1/2 Linux操作系统源代码导读
19
2019/1/2 Linux操作系统源代码导读
20
文件系统类型 特殊文件系统 用来为系统程序员、系统管理员等提供一种容易的方式来操作内核的数据结构并实现操作系统的特殊特征 常用的特殊文件系统
2019/1/2 Linux操作系统源代码导读
21
2019/1/2 Linux操作系统源代码导读
22
文件系统类型的注册 文件系统类型:file_system_type
在系统初始化期间,register_filesystem()用来注册编译时指定的每个文件系统 相应的文件系统对象被插入到file_systems链表中 unregister_filesystem() 2019/1/2 Linux操作系统源代码导读
23
文件系统的挂载 根文件系统 每个文件系统都有自己的根目录 如果一个文件系统的根目录是系统目录树的根目录,那个这个文件系统就是根文件系统
在系统初始化过程中被直接mount 提供系统初始化脚本以及基本命令 每个文件系统都有自己的根目录 如果一个文件系统的根目录是系统目录树的根目录,那个这个文件系统就是根文件系统 其他文件系统可以挂载到系统的目录树上 这样的目录称为挂载点(mount点,安装点) 文件系统之间的挂载关系对应文件系统之间的父子关系 2019/1/2 Linux操作系统源代码导读
24
例如,放在软盘/dev/fd0上的ext2文件系统,可通过下列命令安装在/flp上
mount -t ext2 /dev/fd0 /flp 一般情况下,只允许挂载一次 在umount之前,其他对/dev/fd0的挂载命令会失败 在2.4中,可以挂载多次 不管被挂载多少次,只有一个真实的文件系统,因此只有一个超级块对象 2019/1/2 Linux操作系统源代码导读
25
已挂载文件系统描述符vfsmount 挂载根文件系统 挂载一个文件系统 卸载一个文件系统
第一阶段:安装一个特殊的文件系统,该文件系统仅提供一个作为初始安装点的空目录:init_mount_tree 第二阶段:mount_root 挂载一个文件系统 sys_mount 卸载一个文件系统 sys_umount 2019/1/2 Linux操作系统源代码导读
26
从mount操作到get_sb的过程 sys_mount(char __user * dev_name, char __user * dir_name, char __user * type, unsigned long flags, void __user * data) do_mount(char *dev_name, char *dir_name, char *type_page, unsigned long flags, void *data_page) do_new_mount(struct nameidata *nd, char *type, int flags, int mnt_flags, char *name, void *data) do_kern_mount(const char *fstype, int flags, const char *name, void *data) vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) 2019/1/2 Linux操作系统源代码导读
27
路径名查找 VFS是如何从文件路径名找到相应的索引节点的? 搜索的起点: 分析路径名,将它拆分成一个文件名序列
除了最后一个文件名之外,其他所有文件名必定都是目录名 搜索的起点: 绝对路径:currentfsroot 相对路径:currentfspwd 2019/1/2 Linux操作系统源代码导读
28
在这个索引节点的目录文件中,找到第一个目录名(文件名)所对应的索引节点
首先找到起点目录的索引节点 在这个索引节点的目录文件中,找到第一个目录名(文件名)所对应的索引节点 在第一个目录名的索引节点的目录文件中找到第二个目录名(文件名)所对应的索引节点 …反复,直到文件名序列的最后一项 2019/1/2 Linux操作系统源代码导读
29
在上述查找过程中要处理的其他问题: 路径名查找 对每个目录的访问权限必须进行检查 若是符号链接,需要进行扩展
要考虑符号链接的循环引用(进行处理) 目录名可能是一个文件系统的安装点,必须扩展到一个新的文件系统中 路径名查找 数据结构:struct nameidata 2019/1/2 Linux操作系统源代码导读
30
路径名查找过程 path_lookup_open path_lookup_create __path_lookup_intent_open
do_path_lookup path_walk link_path_walk __link_path_walk do_lookup … 2019/1/2 Linux操作系统源代码导读
31
查找操作的标志 2019/1/2 Linux操作系统源代码导读
32
标准查找操作 要处理的问题 跳过第一个路径名分量前的任何/ 考虑符号链接的查找 检查权限 考虑“.” 考虑“..”
考虑普通目录,要在目录项高速缓存中查找 … 2019/1/2 Linux操作系统源代码导读
33
父路径名的查找 在很多情况下,查找操作的真正目的不是路径名的最后一个分量,而是最后分量的前一个分量 例如创建一个文件时
此时,路径解析的结果中存放最后一个分量所在目录对应的对象 2019/1/2 Linux操作系统源代码导读
34
符号链接的查找 关于符号链接的解析由内核来完成 如何识别这是一个符号链接? 如何处理符号链接的循环情况? 2019/1/2
Linux操作系统源代码导读
35
VFS系统调用的实现 仍然考虑 假定cp执行下列代码片段(实际要更复杂) $ cp /floppy/TEST /tmp/test
inf = open("/floppy/TEST", O_RDONLY, 0); outf = open("/tmp/test", O_WRONLY | O_CREAT | O_TRUNC, 0600); do { len = read(inf, buf, 4096); write(outf, buf, len); } while (len); close(outf); close(inf); 2019/1/2 Linux操作系统源代码导读
36
open()系统调用 read和write系统调用 close系统调用 sys_open sys_write sys_read
sys_close 2019/1/2 Linux操作系统源代码导读
37
打开一个文件:f_op的设置 sys_open(const char __user *filename, int flags, int mode) do_sys_open(int dfd, const char __user *filename, int flags, int mode) do_filp_open(int dfd, const char *pathname, int open_flag, int mode) path_lookup_open或 path_lookup_create nameidata_to_filp(struct nameidata *nd, int flags) __dentry_open中: 2019/1/2 Linux操作系统源代码导读
38
上述几个数据结构之间的关系: Linux内核支持哪些文件系统类型?取决于 加载一个具体的文件系统时(mount) 打开一个文件时
register_filesystem,注册文件系统类型 提供具体的文件系统类型的定义,如romfs,ramfs,ext2fs等 其中包含一个get_sb方法 加载一个具体的文件系统时(mount) 调用get_sb填写文件系统的超级块,包括填写超级块方法 打开一个文件时 确定目录项;确定inode(及文件方法);初始化file结构等 2019/1/2 Linux操作系统源代码导读
39
Project 分析一个具体的文件系统类型的实现,并分析它如何能通过VFS加入到Linux系统中 并做如下实验:
例如romfs;ramfs;ext2;ext3等等 并做如下实验: 使用静态编译或者动态加载的方法,使得你使用的Linux内核支持你分析的文件系统类型 在你的Linux环境中创建一个文件系统映像 将你创建的文件系统映像mount到你的Linux环境中 在你创建的文件系统中进行读写 2019/1/2 Linux操作系统源代码导读
40
Thanks! The end.
Similar presentations