范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

深入剖析虚拟文件系统

  1.前言
  Linux   采用 Virtual Filesystem(VFS)  的概念,通过内核在物理存储介质上的文件系统和用户之间建立起一个虚拟文件系统的软件抽象层,使得 Linux   能够支持目前绝大多数的文件系统,不论它是 windows  、unix   还是其他一些系统的文件系统,都可以挂载在 Linux   上供用户使用。
  VFS, Virtual File System虚拟文件系统 ,也称为虚拟文件系统开关 (Virtual Filesystem Switch  ),就是采用标准的Linux系统调用读写位于不同物理介质上的不同文件系统,即为各类文件系统提供了一个统一的操作界面和应用编程接口,VFS是一个内核软件层 。
  VFS是一个 可以让open()、read()、write()  等系统调用不用关心底层的存储介质和文件系统类型就可以工作的抽象层 :
  2.VFS结构
  这里以Ext4文件系统示例
  VFS中包含着向物理文件系统转换的一系列数据结构,如 VFS超级块(Super Block) 、VFS的Inode 、各种操作函数的转换入口等。Linux中VFS依靠四个主要的数据结构来描述其结构信息,分别为超级块、索引结点、目录项和文件对象 ,这些数据结构大都会与磁盘上的对应上。
  VFS对每种类型的对象都定义了一组必须实现的操作。这些类型的每一个对象都包含了一个指向函数表的指针。函数表列出了实际上实现特定对象的操作函数。  超级块(Super Block) :超级块对象表示一个文件系统。它存储一个已安装的文件系统的控制信息,包括文件系统名称(比如Ext2)、文件系统的大小和状态、块设备的引用和元数据信息(比如空闲列表等等)。超级块与磁盘上文件系统的超级块对应。 所有超级块对象都以  双向循环链表  的形式链接在一起,对象的 自旋锁  ( sb_lock  )保护链表免受多处理器系统上的同时访问。 索引结点(Inode) :索引结点对象存储文件的相关元数据信息,例如:文件大小、设备标识符、用户标识符、用户组标识符等等。Inode  分为两种:一种是VFS  的Inode  ,一种是具体文件系统的Inode  。前者在内存中,后者在磁盘中。所以每次其实是将磁盘中的Inode  调进填充内存中的Inode  ,这样才是算使用了磁盘文件Inode  。当创建一个文件的时候,就给文件分配了一个Inode  。一个Inode只对应一个实际文件,一个文件也会只有一个Inode  (Unix/Linux系统 中目录也是一种文件,打开目录实际上就是打开目录文件。目录文件的结构非常简单,就是一系列目录项(dirent  )的列表。每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码)。 从文件的角度来看,目录就是一个特殊的文件  目录项(Dentry) :引入目录项对象的概念主要是出于方便查找文件的目的。不同于前面的两个对象,目录项对象只存在于内存中,实际对应的是磁盘的目录innode  对象。VFS  在查找的时候,根据一层一层的目录项找到对应的每个目录项的Inode  ,那么沿着目录项进行操作就可以找到最终的文件。文件对象(File) :文件对象描述的是进程已经打开的文件。因为一个文件可以被多个进程打开,所以一个文件可以存在多个文件对象,但多个文件对象其对应的索引节点和目录项对象肯定是惟一的2.1 SuperBlock
  SuperBlock   表示特定加载的文件系统,用于描述和维护文件系统的状态,由 VFS   定义,但里面的数据根据具体的文件系统填充。每个 SuperBlock   代表了一个具体的磁盘分区,里面包含了当前磁盘分区的信息,如文件系统类型、剩余空间等。SuperBlock   的一个重要成员是链表s_list  ,包含所有修改过的 INode  ,使用该链表很容易区分出来哪个文件被修改过,并配合内核线程将数据写回磁盘。SuperBlock   的另一个重要成员是s_op  ,定义了针对其 INode   的所有操作方法,例如标记、释放索引节点等一系列操作。// https://elixir.bootlin.com/linux/v6.0/source/include/linux/fs.h#L1451 结构体已删减 struct super_block {     struct list_head    s_list;               // 指向链表的指针     dev_t               s_dev;                // 设备标识符     unsigned long       s_blocksize;          // 以字节为单位的块大小     loff_t              s_maxbytes;           // 文件大小上限     struct file_system_type    *s_type;       // 文件系统类型     const struct super_operations    *s_op;   // SuperBlock 操作函数,write_inode、put_inode 等     const struct dquot_operations    *dq_op;  // 磁盘限额函数     struct dentry        *s_root;             // 根目录 }
  2.2 DEntry 和 INode
  Linux  文件系统会为每个文件都分配两个数据结构,目录项(DEntry, Directory Entry)和索引节点(INode, Index Node) 。
  DEntry   用来保存文件路径和 INode   之间的映射,从而支持在文件系统中移动。DEntry  由 VFS  维护,所有文件系统共享,不和具体的进程关联。dentry  对象从根目录"/" 开始,每个dentry  对象都会持有自己的子目录和文件,这样就形成了文件树。举例来说,如果要访问**"/home/ccs/a.txt"文件并对他操作,系统会解析文件路径,首先从"/"根目录的 dentry  对象开始访问,然后找到"home/"目录,其次是 "ccs/",最后找到 "a.txt"**的dentry  结构体,该结构体里面d_inode  字段就对应着该文件。// https://elixir.bootlin.com/linux/v6.0/source/include/linux/dcache.h#L81 结构体已删减 struct dentry {     struct dentry *d_parent;     // 父目录     struct qstr d_name;          // 文件名称     struct inode *d_inode;       // 关联的 inode     struct list_head d_child;    // 父目录中的子目录和文件     struct list_head d_subdirs;  // 当前目录中的子目录和文件 }
  每一个 dentry  对象都持有一个对应的inode  对象,表示 Linux   中一个具体的目录项或文件。INode   包含管理文件系统中的对象所需的所有元数据,以及可以在该文件对象上执行的操作。// https://elixir.bootlin.com/linux/v6.0/source/include/linux/fs.h#L593 结构体已删减 struct inode {     umode_t                 i_mode;          // 文件权限及类型     kuid_t                  i_uid;           // user id     kgid_t                  i_gid;           // group id      const struct inode_operations    *i_op;  // inode 操作函数,如 create,mkdir,lookup,rename 等     struct super_block      *i_sb;           // 所属的 SuperBlock      loff_t                  i_size;          // 文件大小     struct timespec         i_atime;         // 文件最后访问时间     struct timespec         i_mtime;         // 文件最后修改时间     struct timespec         i_ctime;         // 文件元数据最后修改时间(包括文件名称)     const struct file_operations    *i_fop;  // 文件操作函数,open、write 等     void                    *i_private;      // 文件系统的私有数据 }
  虚拟文件系统维护了一个  DEntry Cache   缓存,用来保存最近使用的 DEntry  ,加速查询操作。当调用open()  函数打开一个文件时,内核会第一时间根据文件路径到 DEntry Cache   里面寻找相应的 DEntry  ,找到了就直接构造一个file  对象并返回。如果该文件不在缓存中,那么 VFS  会根据找到的最近目录一级一级地向下加载,直到找到相应的文件。期间 VFS  会缓存所有被加载生成的dentry  。
  INode   存储的数据存放在磁盘上,由具体的文件系统进行组织,当需要访问一个 INode   时,会由文件系统从磁盘上加载相应的数据并构造 INode  。一个 INode   可能被多个 DEntry   所关联,即相当于为某一文件创建了多个文件路径(通常是为文件建立硬链接)。对于inode结构而言,可能有三种主要情况:
  存在内存中,未关联到任何文件,也不处于活动使用状态;
  存在内存中,正在由一个或多个进程使用,正在由一个或多个进程使用,通常表示一个文件。两个计数器(i_count和i_nlink)的值都必须大于0。文件内容和inode元数据都与底层块设备上的信息相同。也就是表示从上一次与介质同步依赖,该inode没有改变过;
  处于活动使用状态。其数据内容已经改变,与存储介质上的内容不同。这种状态的inode被称作脏的。
  2.3 fd 与 file
  每个进程都持有一个 fd[]  数组,数组里面存放的是指向file  结构体的指针,同一进程的不同fd  可以指向同一个file  对象;
  file  是内核中的数据结构,表示一个被进程打开的文件,和进程相关联。当应用程序调用open()  函数的时候,VFS   就会创建相应的file  对象。它会保存打开文件的状态,例如文件权限、路径、偏移量等等。// https://elixir.bootlin.com/linux/v6.0/source/include/linux/fs.h#L940 结构体已删减 struct file {     struct path                   f_path;     struct inode                  *f_inode;     const struct file_operations  *f_op;     unsigned int                  f_flags;     fmode_t                       f_mode;     loff_t                        f_pos;     struct fown_struct            f_owner; }  // https://elixir.bootlin.com/linux/v6.0/source/include/linux/path.h#L8 struct path {     struct vfsmount  *mnt;     struct dentry    *dentry; } 3. 抽象层VFS到实现层文件系统3.1挂载
  VFS  可以管理各种文件系统,那么VFS  和文件系统怎么关联的呢?给用户如何展示的呢?通过挂载。
  如下图所示,该系统根文件系统是 Ext3  文件系统,而在其/mnt  目录下面又分别挂载了Ext4  文件系统和XFS  文件系统。最后形成了一个由多个文件系统组成的文件系统树。
  挂载是在用户态发起的命令,也就是我们使用的 mount命令 ,该命令执行的时候需要指定文件系统的类型 (这里假设是Ext2  )和文件系统数据的位置 (也就是device  )。通过这些关键信息,VFS  就可以完成Ext2文件系统的初始化,并将其关联到当前已经存在的文件系统当中,也就是建立起上面所示的文件系统树 。
  挂载的过程中,最重要的数据结构就是 vfsmount  ,vfsmount  代表的是一个挂载点。其次再是dentry  和inode  ,这两个都是对文件的表示,且都会缓存在哈希表中以提高查找的效率。
  其中inode是对磁盘上文件的唯一表示,其中包含文件的元数据(管理数据)和文件数据等内容,但不含文件名称。而 dentry  则是为了Linux  内核中查找文件方便虚拟出来的一个数据结构,其中包含文件名称、子目录(如果存在的话)和关联的inode  等信息。
  dentry  结构体最为关键,其维护了内核中的文件目录树。其中里面比较重要的几个结构体分别是d_name  、d_hash  和d_subdirs  。其中d_name  代表一个路径节点的名称(文件夹名称)、d_hash  则用于构建哈希表,d_subdirs  则是下级目录(或文件)的列表。这样,通过dentry  就可以形成一个非常复杂的目录树。3.2文件处理流程
  文件处理流程包括两步:我们在访问一个文件之前首先要打开它( open  )文件访问,然后进行文件的读写操作(read  或者write  )。
  我们知道,在用户态打开一个文件是返回的是一个文件描述符,其实也就是一个整数值;同时,访问文件也是通过这个文件描述符进行的。那么操作系统是怎么通过这个整数值实现不同类型文件系统的访问呢? 不同文件系统的差异 其实就是inode中初始化的函数指针的差异 。
  在 Linux  操作系统中,文件的打开必须要与进程(或者线程)关联,也就是说一个打开的文件必须隶属于某个进程。
  在 linux  内核当中一个进程通过task_struct  结构体描述,而打开的文件则用file  结构体描述,打开文件 的过程也就是对file结构体的初始化的过程 。在打开文件的过程中会将inode  部分关键信息填充到file  中,特别是文件操作的函数指针。在task_struct  中保存着一个file类型的数组,而用户态的文件描述符其实就是数组的下标。这样通过文件描述符就可以很容易到找到file  ,然后通过其中的函数指针访问数据。
  我们以 Ext2  文件系统的写数据为例 来看看文件处理流程和各个层级之间的关系,如下图。
  在调用用户态的写数据接口的时候,需要传入文件描述符。内核根据文件描述符找到file,然后调用函数接口( file->f_op->write  )文件磁盘数据。其中file结构体的f_op  指针就是在打开文件的时候通过inode  初始化的。4.总结
  虚拟文件系统是操作系统中非常重要的一层抽象, 其主要作用在于让上层的软件,能够用统一的方式,与底层不同的文件系统沟通 。在操作系统与底层的各类文件系统之间,虚拟文件系统提供了标准的操作接口,让操作系统能够很快地支持新的文件系统。也因为 VFS 的支持,众多不同的实际文件系统才能在 Linux 中共存,跨文件系统的操作才能实现。
  附上一张各组件交互图吧
  参考资料:
  《深入理解Linux内核》第三版
  《Linux 虚拟文件系统》

第二届中国米粉节江西南昌开幕近500家企业参展掘金图为第二届中国米粉节主展馆现场,民众在观展。刘力鑫摄中新网南昌11月24日电(徐梦文刘力鑫)第二届中国米粉节24日在江西省会南昌开幕,吸引了近500家全国各地涵盖米粉原料生产机械速中国芯的出路到底在哪里?中国芯起步不算晚,重视程度也不低,那为什么还总是被老美压着打?自2018年老美突然发难以来,中国芯热度空前高潮,我们付出了前所未有的努力,但好像与老美的差距,还是越拉越大,为什么?未来探月工程还有哪些亮点?中国探月工程总设计师吴伟仁解答联合国中国空间探索与创新全球伙伴关系研讨会11月24日闭幕。研讨会期间,我国深空探测的成果与未来规划再次成为热门话题。未来探月工程还有哪些亮点?火星探测会进行采样吗?深空探测还有哪为什么八达岭长城最有名,八达岭长城出名的原因长城被称为世界七大奇迹之一,它见证了中国的历史发展进程,是中国文化的象征。提起长城就不得不提名扬中外的八达岭长城,中外各界名人去北京游玩的必去之地,受到游客的一致好评反响,但是小伙五洲望乡动图概览侨乡潮州潮州市位于广东省最东端,地处粤港澳大湾区与海峡西岸经济区的交汇处,濒临南海。潮州古城至今有2000多年历史,是历代州府之治所,是全球潮文化的发祥地,素有岭海名邦海滨邹鲁的美誉。全市老工业遗存华丽转身大连再添文旅新地标央广网大连11月24日消息(见习记者王松)23日,大连市重点文旅和城市更新项目,大连三十七相文旅科技产业园正式启幕。对于市民和游客来说,此后大连又多了一个打卡新地标。当天,还举办了无人机焰火秀助阵首届长沙市旅游发展大会长沙望城区铜官窑古镇夜空被焰火点亮。杨华峰摄绚丽的烟火在空中燃放。杨华峰摄游人乘船观焰火。杨华峰摄古镇上空焰火绚丽。杨华峰摄古镇上空无人机表演秀。杨华峰摄无人机表演助阵首届长沙市旅湖北这些景区场馆暂停开放来源长江云近日湖北部分场馆景区发布暂停开放通知详情如下湖北美术馆暂停对外开放根据当前疫情防控形势,为切实保障广大观众朋友身体健康,湖北美术馆自2022年11月23日起暂停对外开放,为什么现在酒店查房越来越少了?保洁阿姨有3点原因大家出门旅游出差等等,在外面都会选择住酒店,只不过现在因为疫情的影响,大家出门少了酒店的生意惨淡了很多,但也不是没人,只是没之前那么多罢了。但是大家有没有发现一件怪事,现在酒店查房爱上姑苏这座城苏州,是一座城市,高楼林立,车水马龙,苏州,又是一处园林,小桥流水粉墙黛瓦。苏州,古典与现代并存,苏州,魅力和活力同在。因为一个人而喜欢一座城,我就是这样爱上了苏州的题记知道苏州,一个止痛除寒中成药,逼出骨缝中的风寒湿毒治全身疼痛大家好,我是沈医生,今天给大家介绍一个方子,只有简单五味药,却可起到补阳活血,通络止痛的功效,可逼走骨缝中的风寒湿邪,缓解腰椎病,关节炎,坐骨神经痛等等病症。生活中经常感觉手脚冰凉
老中医治疗骨质增生的经验方法,良方难得,请好好珍惜中医认为,腰椎骨质增生与外伤劳损瘀血阻络感受风寒湿邪痰湿内阻肝肾亏虚等有关。这种增生腰痛一般好发于中老年人。患者人过中年,阴液自亏,肝肾阴精不足,气血渐虚,上不能濡养清窍,常见头晕阳气不足,结节生!张仲景的3味药,助你回阳救逆通百络阳气,是生命之火。黄帝内经说阳气者,若天与日,失其所,则折寿而不彰。阳气的作用很大,我们人体的五脏六腑全靠阳气来推动。换句话说,我们的生命就是一团阳气组成的,阳气不到的地方,就是病倒计时2天,苹果春季发布会即将到来,iPhoneSE3等多款产品曝光作为全球最受关注的科技公司,苹果一直都吸引了很多数码科技爱好者的关注,以至于发布新款产品都引来很多粉丝的期待,在创新领域上苹果也一直领先,同时拥有A系处理器和iOS系统让苹果的手机36岁宝妈一年四季油敷,老公天天夸我皮肤嫩自从前年接触了油敷就根本停不下来!真的适合我们现在这个年纪给大家分享一下我油敷的过程吧,之前也有姐妹问过,就在这里一一解答了1。首先我们要先用温和的洗面奶把脸干净,不化妆也要洗去一MySQL索引失效的15种场景无论你是技术大佬,还是刚入行的小白,时不时都会踩到Mysql数据库不走索引的坑。常见的现象就是明明在字段上添加了索引,但却并未生效。前些天就遇到一个稍微特殊的场景,同一条SQL语句CBA最新排名辽篮重新夺回第一,广东滑至第六,吉林豪取九连胜北京时间3月8日CBA常规赛继续上演,在刚刚已经结束的两场比赛中深圳队和吉林队继续延续自己的胜场数,这样一来CBA积分榜排名也发生了不小的变化,特别是卫冕冠军广东队已经被深圳队反超A股全面下跌!市场见底了吗?本周最低点出现了在白酒的拉升下,早盘冲高,市场有一个弱反弹,这种反弹根本不必思考,直接高抛就行了,之前我给大家分享过经验,大阴线下跌后面的开盘冲高,是离场的最佳时机,准确率80。真正的见底,不会是快本停播5个月,快乐家族现状有人仍是主持C位,有人在待业距离快本停播,已经过去5个月了,虽然名义上,快乐大本营已经改版成你好,星期六,而主持人仍然是以何炅老师为主,但不可否认,关于两档节目的争议就没有停过。不可否认,快乐大本营作为王牌节格力终于患上了董明珠依赖症,68岁的她如何领导格力破局?2月底,格力电器股东大会,再一次选举董明珠担任公司董事长,任期三年,而且是全票通过当选。全票当选,彰显出董明珠在格力的地位无人可以取代。二号人物长期缺失的格力,越来越离不开董明珠的想一直住下去的仙本那小渔村春日鉴片官想一直住下去的仙本那小渔村!如果你仅仅想来这里拍照那大可不必。天涯镇的精髓在于,午后悠闲的海风一边享受黄昏,一边享受海鲜巷子的尽头是海滩坐在石阶上等阳光散去或者找家喜欢的发热咽痛,可能不是感冒,而是另一种更严重的病如果一个人突然觉得疲乏无力还怕冷打寒战吃东西没胃口吞咽时有疼痛感大家第一反应是不是觉得这个人感冒了?但养生君提醒大家出现这些症状如果还伴有颈部疼痛就需要特别警惕另一种病甲状腺炎病例