版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
虚拟文件系统VFS总结虚拟文件系统VFS介绍郑萍萍03991目录Linux文件系统组件的体系结构VFS文件系统概述VFS目录树文件系统注册VFS目录树的建立VFS下目录的建立在VFS树中挂载文件系统打开一个文件Linux文件系统组件的体系结构总体上说Linux下的文件系统主要可分为三大块一是上层的文件系统的系统调用二是虚拟文件系统VFS(VirtualFilesystemSwitch)三是挂载到VFS中的各实际文件系统,例如ext2,jfs等
Linux文件系统组件的体系结构Linux文件系统组件包括用户空间和内核空间两部分组成
用户空间包含一些应用程序(例如,文件系统的使用者)和GNUC库(glibc),它们为文件系统调用(打开、读取、写和关闭)提供用户接口内核空间由加载在系统内核中的系统调用接口、虚拟文件系统(VFS)、实际文件系统(ext2、JFS等)以及文件系统缓存和设备驱动程序组成Linux文件系统组件的体系结构Linux文件系统组件的体系结构系统调用接口的作用就像是交换器,它将系统调用从用户空间发送到内核空间中的适当端点
VFS是底层文件系统的主要接口,这个组件导出一组接口,然后将它们抽象到各个文件系统,各个文件系统的行为可能差异很大每个文件系统实现(比如ext2、JFS等等)导出一组通用接口,供VFS使用缓冲区缓存会缓存文件系统和相关块设备之间的请求。以最近使用(LRU)列表的形式管理缓冲区缓存
主要结构Linux以一组通用对象的角度看待所有文件系统,这些对象是超级块(superblock)、inode、dentry和文件超级块结构表示一个文件系统。它包含管理文件系统所需的信息,包括文件系统名称(比如ext2)、文件系统的大小和状态、块设备的引用和元数据信息(比如空闲列表等等)VFS作为Linux文件系统接口的根层,也包括超级块(superblock)、inode、dentry等对象
目录Linux文件系统组件的体系结构VFS文件系统概述VFS目录树文件系统注册VFS目录树的建立VFS下目录的建立在VFS树中挂载文件系统打开一个文件VirtualFileSystem(或者被称为VirtualFilesystemSwitch)
是Linux内核中的一个软件层用于给用户空间的程序提供文件系统接口提供了内核中的一个抽象功能,把各种差异很大的文件系统抽象成Linux能识别的文件系统有两个针对文件系统对象的缓存(inode和dentry)VFS文件系统概述VFS超级块VFS超级块:VFS和ext2文件系统一样也使用超级块和索引节点来描述和管理系统中的文件。每个被注册的文件系统都会有一个VFS超级块信息设备标识符。这是存储文件系统的物理块设备的设备标识符,如系统中第一个IDE磁盘/dev/hda1的标识符是0x301索引节点指针。安装索引节点指针指向被安装的子文件系统的第一个索引节点;覆盖索引节点指针指向安装文件系统目录(安装点)的索引节点。根文件系统的VFS超级块中没有覆盖索引节点指针数据块大小。文件系统中数据块的字节数VFS超级块超级块操作集。指向一组超级块操作例程的指针,VFS利用它们可以读写索引节点和超级块文件系统类型。指向所安装的文件系统类型的指针文件系统的特殊信息。指向文件系统所需要信息的指针可以看出,VFS超级块的结构比ext2文件系统的超级块简单,主要增加的是超级块操作集,它用于对不同文件系统进行操作,对于超级块本身并无作用。VFS超级块inode介绍inode表示文件系统中的一个对象,它具有惟一标识符文件系统中管理的每个对象(文件或目录)在Linux中表示为一个inodeinode包含管理文件系统中的对象所需的所有元数据(包括可以在对象上执行的操作)各个文件系统提供将文件名映射为惟一inode标识符和inode引用的方法inode介绍dentry介绍dentry是个目录缓存(包括父路径parentdirectory和子节点childofparentlist信息)主要用于维护目录和文件之间的关系,从而支持在文件系统中移动对于inode缓存中的每个inode,在目录缓存中都有一个对应的dentry
dentry介绍structdentry{structinode*d_inode;/*Wherethenamebelongsto-NULLisstructhlist_noded_hash;/*lookuphashlist*/structdentry*d_parent;/*parentdirectory*/上一级的目录
structqstrd_name;structlist_headd_lru;/*LRUlist*//**d_childandd_rcucansharememory*/union{structlist_headd_child;/*childofparentlist*/structrcu_headd_rcu;}d_u;structlist_headd_subdirs;/*ourchildren*/节点下面的所有文件和目录};目录Linux文件系统组件的体系结构VFS文件系统概述VFS目录树文件系统注册VFS目录树的建立VFS下目录的建立在VFS树中挂载文件系统打开一个文件VFS目录树VFS是一种软件机制,也许称它为Linux的文件系统管理者更确切点,与它相关的数据结构只存在于物理内存当中在每次系统初始化期间,Linux都首先要在内存当中构造一棵VFS的目录树(在Linux的源代码里称之为namespace),实际上便是在内存中建立相应的数据结构VFS中的各目录其主要用途是用来提供实际文件系统的挂载点
VFS目录树下图是一种可能的目录树在内存中的影像
rootfs文件系统rootfs文件系统是VFS存在的基础,是一个特殊的基于内存的文件系统,只提供一个空目录以及为其他真实的文件系统提供一个初始的挂载点在Linux中,rootfs是必不可少的,主要是便于更换挂载的根“/”文件系统文件系统是指可能会被挂载到目录树中的各个实际文件系统,"rootfs"、"proc"、"ext2"
目录Linux文件系统组件的体系结构VFS文件系统概述VFS目录树文件系统注册VFS目录树的建立VFS下目录的建立在VFS树中挂载文件系统打开一个文件Linux下挂载的文件系统[root@zpp~]#cat/proc/mountsrootfs/rootfsrw00/proc/procprocrw,nodiratime00none/devtmpfsrw00/dev/root/ext3rw00none/devtmpfsrw00none/selinuxselinuxfsrw00/proc/procprocrw,nodiratime00/proc/bus/usb/proc/bus/usbusbfsrw00/sys/syssysfsrw00none/dev/ptsdevptsrw00/dev/sda1/bootext3rw00none/dev/shmtmpfsrw00none/proc/sys/fs/binfmt_miscbinfmt_miscrw00sunrpc/var/lib/nfs/rpc_pipefsrpc_pipefsrw00[root@zpp~]#
文件系统的数据结构在Linux源代码中,每种实际的文件系统用以下的数据结构表示structfile_system_type{ constchar*name; intfs_flags; structsuper_block*(*get_sb)(structfile_system_type*,int,constchar*,void*); void(*kill_sb)(structsuper_block*); structmodule*owner; structfile_system_type*next; structlist_headfs_supers;};文件系统注册文件系统的注册过程实际上就是将表示各实际文件系统的structfile_system_type数据结构的实例化,然后形成一个链表,并在内核中用一个名为file_systems的全局变量来表示。
structvfsmount{structlist_headmnt_hash;structvfsmount*mnt_parent;/*fswearemountedon*/structdentry*mnt_mountpoint;/*dentryofmountpoint*/structdentry*mnt_root;/*rootofthemountedtree*/structsuper_block*mnt_sb;/*pointertosuperblock*/structlist_headmnt_mounts;/*listofchildren,anchoredhere*/structlist_headmnt_child;/*andgoingthroughtheirmnt_child*/intmnt_flags;/*4bytesholeon64bitsarches*/constchar*mnt_devname;/*Nameofdevicee.g./dev/dsk/hda1*/structlist_headmnt_list;};rootfs文件系统注册rootfs文件系统是VFS存在的基础rootfs的注册过程是Linux内核初始化阶段不可分割的一部分通过init_rootfs()这一初始化函数来完成一般文件系统(ext2,ext3)的注册都是通过module_init宏以及do_initcalls()函数来完成rootfs文件系统注册int__initinit_rootfs(void){returnregister_filesystem(&rootfs_fs_type);}intregister_filesystem(structfile_system_type*fs){intres=0;structfile_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);returnres;}rootfs文件系统注册rootfs文件系统注册完成后的file_systems链表结构如下图所示
目录Linux文件系统组件的体系结构VFS文件系统概述VFS目录树文件系统注册VFS目录树的建立VFS下目录的建立在VFS树中挂载文件系统打开一个文件
VFS目录树的建立Linux在初始化阶段是如何建立根结点的,即“/”目录的建立过程:
首先,init_rootfs()初始化函数通过调用register_filesystem(&rootfs_fs_type)函数来完成rootfs文件系统注册然后,init_mount_tree()函数调用do_kern_mount(“rootfs”,0,“rootfs”,NULL)来挂载前面已经注册了的rootfs文件系统最后,init_mount_tree()函数会为系统最开始的进程(即init_task进程)准备它的进程数据块中的namespace域(内存空间),主要目的是将do_kern_mount()函数中建立的mnt和dentry信息记录在了init_task进程的进程数据块中,这样所有以后从init_task进程fork出来的进程(子进程)也都先天地继承了这一信息
VFS目录树的建立init_mount_tree()
调用do_kern_mount(“rootfs”,0,“rootfs”,NULL)
挂载已注册的rootfs文件系统,初始化mnt、sb、dentry等2init_rootfs()初始化rootfs
register_filesystem(&rootfs_fs_type)函数完成rootfs文件系统注册
1调用3init_task()准备进程数据块中的namespace域,将do_kern_mount()函数中建立的mnt和dentry信息记录在了init_task进程的进程数据块中
调用4挂载VFS目录树的建立问题应该先有挂载目录,然后再在其上挂载相应的文件系统,然而此时VFS似乎并没有建立其根目录?
VFS目录树的建立没关系,这是因为这里我们调用的是do_kern_mount(),这个函数内部自然会创建我们最关心也是最关键的根目录(在Linux中,目录对应的数据结构是structdentry)
VFS目录树的建立
do_kern_mount()做的主要工作1)调用alloc_vfsmnt()函数在内存里申请了一块该类型的内存空间(structvfsmount*mnt),并初始化其部分成员变量2)调用get_sb_nodev()函数在内存中分配一个超级块结构(structsuper_block)sb,并初始化其部分成员变量,将成员s_instances(文件系统的超级块实例化成内核中的文件系统超级块信息)插入到rootfs文件系统类型结构中的fs_supers指向的双向链表中3)通过rootfs文件系统中的read_super函数指针调用ramfs_read_super()函数
VFS目录树的建立4)ramfs_read_super()函数调用ramfs_get_inode()在内存中分配了一个inode结构(structinode)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文件系统中相应的函数接口所接管5)ramfs_read_super()函数在分配和初始化了inode结构之后,会调用d_alloc_root()函数来为VFS的目录树建立起关键的根目录(structdentry)dentry,并将dentry中的d_sb指针指向sb,d_inode指针指向inode6)将mnt中的mnt_sb指针指向sb,mnt_root和mnt_mountpoint指针指向dentry,而mnt_parent指针则指向自身VFS目录树的建立1alloc_vfsmnt()申请内存空间structvfsmount*mnt
2调用get_sb_nodev()在内存中分配一个超级块结构,将成员s_instances插入到rootfs文件系统类型结构中do_kern_mount
()调用rootfs文件系统中的read_super函数指针调用ramfs_read_super()
函数3调用4ramfs_get_inode()
在内存中分配了一个inode结构,并初始化其部分成员变量d_alloc_root()
函数来为VFS的目录树建立起关键的根目录dentry调用5调用mnt中的mnt_sb指针指向sb,mnt_root和mnt_mountpoint指针指向dentry,而mnt_parent指针则指向自身。66
VFS目录树的建立图中mnt、sb、inode、dentry结构块下方的数字表示它们在内存里被分配的先后顺序。目录Linux文件系统组件的体系结构VFS文件系统概述VFS目录树文件系统注册VFS目录树的建立VFS下目录的建立在VFS树中挂载文件系统打开一个文件VFS下目录的建立Linux下用系统调用sys_mkdir来在VFS目录树中增加新的节点。同时为配合路径搜索,引入了下面数据结构:
structnameidata{structdentry*dentry;//要建目录的父目录的信息
structvfsmount*mnt;//文件系统挂载点
structqstrlast;//所查找路径的最后一个节点(即待建目录或文件)的信息
unsignedintflags;intlast_type;};这个数据结构在路径搜索的过程中用来记录相关信息,起着类似"路标"的作用。
VFS下目录的建立"皮之不存,毛将焉附"
要在VFS中建立一个新的目录,首先要对该目录进行搜索,搜索的目的是找到将要建立的目录的父目录的相关信息比如要建立目录/home/ricard,那么首先必须沿目录路径进行逐层搜索:从根目录找起,然后在根目录下找到目录home,然后再往下,便是要新建的目录名ricardVFS下目录的建立在VFS的根目录下建立一个新的目录"/dev"的过程:1)为建立目录“/dev”调用sys_mkdir(“/dev”,0700),其中参数0700只是限定将要建立的目录的某种模式2)调用path_lookup发现“/dev”是以“/”开头,所以从当前进程的根目录开始往下查找3)然后调用函数path_walk接着往下查找,找到最后返回的信息=“dev”,nd.last.len=3,nd.last_type=LAST_NORM。其nd是指structnameidata返回的dentry,mnt等信息VFS下目录的建立4)调用lookup_create()函数,新分配了一个structdentry结构的内存空间,用于记录dev目录所对应的信息,该dentry结构将会挂接到其父目录中,也就是“/”目录对应的dentry结构中,由链表实现这一关系5)接下来会再分配一个structinode结构6)在同一文件系统下建立新的目录时并不需要重新分配一个超级块结构,因为毕竟它们都属于同一文件系统,因此一个文件系统只对应一个超级块Inode中的i_sb和dentry中的d_sb需要强调一点的是,既然rootfs文件系统被mount到了VFS树上了,那么它在sys_mkdir的过程中必然会参与进来
VFS下目录的建立建立目录"/dev"sys_mkdir("/dev",0700)调用1调用2path_lookup("/dev",LOOKUP_PARENT,&nd)do_path_lookup()
从当前进程的"/"根目录开始往下查找
调用3path_walk()接着往下查找,返回的信息是="dev",nd.last.len=3,nd.last_type=LAST_NORM
调用45为接下来建立新的节点收集了必要的信息lookup_create()建立新目录节点
structdentry()分配内存空间,用于记录dev目录所对应的信息,该dentry结构将会挂接到其父目录中
调用6分配一个structinode结构,Inode中的i_sb和dentry中的d_sb分别都指向rootfs的sb
7在同一文件系统下建立新的目录时并不需要重新分配一个超级块结构,因为毕竟它们都属于同一文件系统,因此一个文件系统只对应一个超级块。成功地在VFS的目录树中新建立目录"/dev"
8VFS下目录的建立目录Linux文件系统组件的体系结构VFS文件系统概述VFS目录树文件系统注册VFS目录树的建立VFS下目录的建立在VFS树中挂载文件系统打开一个文件在VFS树中挂载文件系统将hda2上的根文件系统(文件系统类型为ext2)安装到“/dev”目录上初始过程由sys_mount()系统调用函数发起该函数原型声明如下:asmlinkagelongsys_mount(char*dev_name,char*dir_name,char*type,unsignedlongflags,void*data);
其中,参数char*type为标识将要安装的文件系统类型字符串,对于ext2文件系统而言,就是“ext2”。参数flags为安装时的模式标识数sys_mount()函数将来自用户内存空间(userspace)的参数sys_mount("hda2","/dev","ext2",…)拷贝到内核空间调用do_mount()函数开始真正的安装文件系统的工作在VFS树中挂载文件系统do_mount()函数会首先调用path_lookup()函数来得到安装点的相关信息。path_lookup()函数的责任就是对文件路径名进行搜索,直到找到目标文件所属目录所对应的dentry或者目标直接就是一个目录,只要记住path_lookup()会返回一个目标目录即可。do_mount()函数会调用do_add_mount()函数来向VFS树中安装点“/dev”安装一个实际的文件系统。主要完成了两件重要事情:一是获得一个新的安装区域块,二是将该新的安装区域块加入了安装系统链表。在VFS树中挂载文件系统sys_mount(char__user*dev_name,char__user*dir_name,char__user*type,unsignedlongflags,void__user*data)
将来自用户内存空间(userspace)的参数拷贝到内核空间
sys_mount("hda2","/dev","ext2",…)
do_mount()开始真正的安装文件系统的工作
调用
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 启动市场调研工作通知函(3篇)范文
- 关于2026年新商务合作协议的通知(6篇)
- 沪外教版七年级英语上册Unit3单元质检卷(含答案)
- 银行业务拓展团队销售KPI考核表
- 智能仓储系统选择与应用指引
- 家庭厨房安全使用与紧急处理指南
- 乡村能源管理师工作效率考核表
- 游泳馆用户游泳安全操作规范手册
- 网站UI设计师界面美观度考核表
- 产品开发效率与质量考评表
- 浙江天域名校协作体2027届高三上学期10月学科练习数学试卷(含答案)
- 2026年国家能源集团笔试试题题库答案
- 浙江省高校招生职业技能考试技能操作合格标准(试行)
- 2026年医药代表合规推广行为准则与案例
- 《AI智能体搭建与应用(基于Coze)(慕课版)》 课件 项目1-4 AI 智能体概述-创作提效:内容生成智能体
- 2026年中耳炎(术后)出院耳部护理与防复发
- NB-T+11396-2023+生物质气化多联产流化床气化炉技术条件
- 2025人教版二年级数学上册《校园小导游》教案
- 2024年山东省东营市辅警协警笔试笔试模拟考试题(含答案)
- 家长课堂学会自立课件
- GB/T 750-2024水泥压蒸安定性试验方法
评论
0/150
提交评论