在VFS接口实现中,涉及大量的数据结构。VFS结构由两个部分组成:文件文件系统,这些都需要管理和抽象。

1.文件表示

inode是Linux内核选择用于表示内容和相关元数据的方法。在抽象对底层文件系统的访问时,并未使用固定的函数,而是使用了函数指针。这函数指针保存在两个结构中,包括了所有相关的函数。
(1)inode操作:创建链接、文件重命名、在目录中生成新文件、删除文件。

const struct inode_operations    *i_op;

(2)文件操作:作用于文件的数据内容。他们包含一些显然的操作(如读和写),还包括如设置文件位置指针和创建内存映射之类的操作。

const struct file_operations *i_fop;

打开的文件总是分配到系统中一个特定的进程,内核必须在数据结构中存储文件和进程之间的关联,各个文件系统实现也能在VFS inode中存储自身的数据(不通过VFS层操作)。

2.文件系统和超级块信息

VFS支持的文件系统类型通过一种特殊的内核对象链接进来,该对象提供了一种读取超级块的方法。除了文件系统的关键信息(如块长度、最大文件长度等等)之外,超级块还包含了读、写、操作inode的函数指针。
内核还建立了一个链表,包含所有活动文件系统的超级块实例。之所以使用活动(active)这个术语替代已装载(mounted),是因为在某些环境中,有可能使用一个超级块对应几个装载点。
尽管每个文件系统在file_system_type中只出现一次,但所有超级块实例的链表中,可能有几个同一文件系统类型的超级块实例,因为在各个块设备/分区上可能存储了同一类型的几个文件系统。

struct file_system_type {const char *name;int fs_flags;
#define FS_REQUIRES_DEV     1
#define FS_BINARY_MOUNTDATA 2
#define FS_HAS_SUBTYPE      4
#define FS_USERNS_MOUNT     8   /* Can be mounted by userns root */
#define FS_USERNS_DEV_MOUNT 16 /* A userns mount does not imply MNT_NODEV */
#define FS_USERNS_VISIBLE   32  /* FS must already be visible */
#define FS_RENAME_DOES_D_MOVE   32768   /* FS will handle d_move() during rename() internally. */struct dentry *(*mount) (struct file_system_type *, int,const char *, void *);struct dentry *(*mount2) (struct vfsmount *, struct file_system_type *, int,const char *, void *);void *(*alloc_mnt_data) (void);void (*kill_sb) (struct super_block *);struct module *owner;struct file_system_type * next;struct hlist_head fs_supers;struct lock_class_key s_lock_key;struct lock_class_key s_umount_key;struct lock_class_key s_vfs_rename_key;struct lock_class_key s_writers_key[SB_FREEZE_LEVELS];struct lock_class_key i_lock_key;struct lock_class_key i_mutex_key;struct lock_class_key i_mutex_dir_key;
};

3.VFS的inode结构源码

/** Keep mostly read-only and often accessed (especially for* the RCU path lookup and 'stat' data) fields at the beginning* of the 'struct inode'*/
struct inode {umode_t           i_mode;unsigned short       i_opflags;kuid_t            i_uid;kgid_t            i_gid;unsigned int      i_flags;#ifdef CONFIG_FS_POSIX_ACLstruct posix_acl  *i_acl;struct posix_acl *i_default_acl;
#endifconst struct inode_operations *i_op;struct super_block    *i_sb;struct address_space  *i_mapping;#ifdef CONFIG_SECURITYvoid           *i_security;
#endif/* Stat data, not accessed from path walking */unsigned long      i_ino;/** Filesystems may only read i_nlink directly.  They shall use the* following functions for modification:**    (set|clear|inc|drop)_nlink*    inode_(inc|dec)_link_count*/union {const unsigned int i_nlink;unsigned int __i_nlink;};dev_t           i_rdev;loff_t           i_size;struct timespec      i_atime;struct timespec     i_mtime;struct timespec     i_ctime;spinlock_t      i_lock; /* i_blocks, i_bytes, maybe i_size */unsigned short          i_bytes;unsigned int       i_blkbits;enum rw_hint      i_write_hint;blkcnt_t       i_blocks;#ifdef __NEED_I_SIZE_ORDEREDseqcount_t     i_size_seqcount;
#endif/* Misc */unsigned long       i_state;struct mutex        i_mutex;unsigned long       dirtied_when;   /* jiffies of first dirtying */unsigned long        dirtied_time_when;struct hlist_node i_hash;struct list_head i_io_list;  /* backing dev IO list */
#ifdef CONFIG_CGROUP_WRITEBACKstruct bdi_writeback  *i_wb;      /* the associated cgroup wb *//* foreign inode detection, see wbc_detach_inode() */int          i_wb_frn_winner;u16         i_wb_frn_avg_time;u16           i_wb_frn_history;
#endifstruct list_head  i_lru;      /* inode LRU list */struct list_head    i_sb_list;union {struct hlist_head  i_dentry;struct rcu_head        i_rcu;};u64         i_version;atomic_t      i_count;atomic_t        i_dio_count;atomic_t        i_writecount;
#ifdef CONFIG_IMAatomic_t       i_readcount; /* struct files open RO */
#endifconst struct file_operations  *i_fop; /* former ->i_op->default_file_ops */struct file_lock_context *i_flctx;struct address_space   i_data;struct list_head i_devices;union {struct pipe_inode_info *i_pipe;struct block_device *i_bdev;struct cdev     *i_cdev;char            *i_link;};__u32         i_generation;#ifdef CONFIG_FSNOTIFY__u32            i_fsnotify_mask; /* all events this inode cares about */struct hlist_head   i_fsnotify_marks;
#endif#if IS_ENABLED(CONFIG_FS_ENCRYPTION)struct fscrypt_info   *i_crypt_info;
#endifvoid          *i_private; /* fs or device private pointer */
};

4.VFS与各文件系统的关系

VFS之基本数据结构

VFS支持三种类型的文件系统:基于磁盘的文件系统、特殊的文件系统和网络文件系统。
基于磁盘的文件系统:管理在非易失去介质存储的文件。这种类型的文件系统最多,比如常见的ext2/3/4、fat、ntfs等。
特殊的文件系统:在内核中生成,是一种使用户应用程序与用户通信的方法,比如常见的proc文件系统,它存储于内存,不占用硬件存储空间。
网络文件系统:这种文件系统可以通过网络访问另一台计算机上的数据,相当于连接到本地计算机一样。比如nfs文件系统。

5.VFS基本数据结构

VFS通用文件模型包含有4种基本的数据结构,通过这几个数据结构实现将硬盘上的文件抽象到内存中:

  • 超级块
  • 目录项
  • 索引节点
  • 文件

6.inode操作

内核提供了大量函数对inode进行操作。为此定义了一个函数指针的集合,以抽象这些操作,因为实际数据是通过具体的文件系统的实现操作的,调用接口不变,但实际工作是由特定实现函数完成的。

struct inode_operations {struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);//根据文件系统对象的名称(表示为字符串)查找其inode实例const char * (*follow_link) (struct dentry *, void **);int (*permission) (struct inode *, int);int (*permission2) (struct vfsmount *, struct inode *, int);struct posix_acl * (*get_acl)(struct inode *, int);int (*readlink) (struct dentry *, char __user *,int);void (*put_link) (struct inode *, void *);int (*create) (struct inode *,struct dentry *, umode_t, bool);//VFS通过系统调用create()和open()来调用该函数,从而为dentey对象创建一个新的索引节点,在创建时使用inode指定初始的一个模式。int (*link) (struct dentry *,struct inode *,struct dentry *);//该函数被系统调用link()调用,用来创建硬链接,硬链接名称由dentry指定,链接对象是dir目录中old_dentry目录项所指定。int (*unlink) (struct inode *,struct dentry *);//该函数被系统调用unlink()调用,从目录dir中删除有目录项dentry指定的索引节点对象。int (*symlink) (struct inode *,struct dentry *,const char *);int (*mkdir) (struct inode *,struct dentry *,umode_t);//系统调用mkdir()调用,创建一个新的目录,创建时使用mode指定初始模式。int (*rmdir) (struct inode *,struct dentry *);//系统调用rmdir调用,创建一个新的目录,创建时使用mode指定初始模式。int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);int (*rename) (struct inode *, struct dentry *,struct inode *, struct dentry *);int (*rename2) (struct inode *, struct dentry *,struct inode *, struct dentry *, unsigned int);int (*setattr) (struct dentry *, struct iattr *);int (*setattr2) (struct vfsmount *, struct dentry *, struct iattr *);int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);ssize_t (*listxattr) (struct dentry *, char *, size_t);int (*removexattr) (struct dentry *, const char *);int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,u64 len);int (*update_time)(struct inode *, struct timespec *, int);int (*atomic_open)(struct inode *, struct dentry *,struct file *, unsigned open_flag,umode_t create_mode, int *opened);int (*tmpfile) (struct inode *, struct dentry *, umode_t);int (*set_acl)(struct inode *, struct posix_acl *, int);
} ____cacheline_aligned;

inode结构有两个指针(i_op和i_fop),file_operations用于操作文件中包含的数据,inode_operations负责管理结构性的操作(删除一个文件)和文件相关的元数据(属性等)。
inode_operations介绍

7.目录项缓存

由于块设备速度较慢,可能需要很长时间才能找到与一个文件名关联的inode,即使设备数据已经在页缓存。linux使用目录项缓存(简称dentry缓存)来快速访问此前的查找操作的结果。该缓存围绕着struct dentry建立。
在VFS连同文件系统实现读取的一个目录项(目录或文件)的数据之后,则创建一个dentry实例,以缓存找到的数据。

struct dentry {/* RCU lookup touched fields *///由d_lock保护,目录项缓存标识unsigned int d_flags;        /* protected by d_lock */seqcount_t d_seq;      /* per dentry seqlock *///内核使用dentry_hashtable对detry进程管理struct hlist_bl_node d_hash;    /* lookup hash list *///父目录的目录项struct dentry *d_parent; /* parent directory *///目录项名称struct qstr d_name;//存放短的文件名称struct inode *d_inode;        /* Where the name belongs to - NULL is* negative */unsigned char d_iname[DNAME_INLINE_LEN]; /* small names *//* Ref lookup also touches following */struct lockref d_lockref;   /* per-dentry lock and refcount */const struct dentry_operations *d_op;struct super_block *d_sb;    /* The root of the dentry tree */unsigned long d_time;      /* used by d_revalidate */void *d_fsdata;           /* fs-specific data */struct list_head d_lru;       /* LRU list */struct list_head d_child; /* child of parent list */struct list_head d_subdirs;   /* our children *//** d_alias and d_rcu can share memory*/union {struct hlist_node d_alias; /* inode alias list */struct rcu_head d_rcu;} d_u;
};

缓存的组织

dentry结构不仅使得易于处理文件系统,对提高系统性能也很关键。dentry对象在内存中的组织,涉及下面两个部分。
(1)一个散列表(dentry_hashtable)包含了所有的dentry对象。
(2)一个LRU(最近最少使用,least recently used)链表,其中不再使用的对象将授予一个最后宽期限,宽期限过后才从内存移除。

dentry操作

dentry_operation结构保存了一些指向各种特定文件系统可以对dentry对象执行的操作函数指针。

struct dentry_operations {int (*d_revalidate)(struct dentry *, unsigned int);int (*d_weak_revalidate)(struct dentry *, unsigned int);//计算散列值,该值用于将对象放置到dentry散列表中。int (*d_hash)(const struct dentry *, struct qstr *);//比较两个dentry对象的文件名称int (*d_compare)(const struct dentry *, const struct dentry *,unsigned int, const char *, const struct qstr *);int (*d_delete)(const struct dentry *);void (*d_release)(struct dentry *);void (*d_prune)(struct dentry *);void (*d_iput)(struct dentry *, struct inode *);char *(*d_dname)(struct dentry *, char *, int);struct vfsmount *(*d_automount)(struct path *);int (*d_manage)(struct dentry *, bool);struct inode *(*d_select_inode)(struct dentry *, unsigned);void (*d_canonical_path)(const struct path *, struct path *);struct dentry *(*d_real)(struct dentry *, struct inode *);
} ____cacheline_aligned;

通用文件模型及VFS-VFS结构相关推荐

  1. vfs文件体系结构图linux,VFS文件系统结构分析

    本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载.但转载请保持文档的完整性,并注明原作者及原链接.内容可任意使用,但对因使用该内容引起的后果不做任何保证. 作者:fireaxe_hq@ho ...

  2. 文件操作函数在VFS层的实现

    文件操作函数在VFS层的实现 参考"Understanding Linux kernel"中的"12.6 Implementations of VFS System Ca ...

  3. linux文件 i节点结构,Linux 文件描述符 文件表项 i节点结构

    Linux的VFS(虚拟文件系统)学习起来很痛苦,看源码不太明智,看完分析完就忘且太浪费时间,懂了后也无法应用在实际场合中.所以这里只是讨论下文件描述符,文件表项(file结构体)和inode,理清实 ...

  4. linux存储--文件描述符以及file结构体(一)

    一.什么是文件描述符 在Linux下一切皆文件,对于内核而言,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数,当打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符.当读. ...

  5. “通用大模型”趋势下,AI未来当如何?

    整理 | 张洁 近年来,在互联网.传统企业深度拥抱数字化.云原生等新兴技术的趋势下, AI已成为不可或缺的底层支撑.不过,站在开发者角度来看,AI开发的高门槛.匮乏的开发工具.庞大的数据量,都让很多开 ...

  6. keras系列︱Sequential与Model模型、keras基本结构功能(一)

    不得不说,这深度学习框架更新太快了尤其到了Keras2.0版本,快到Keras中文版好多都是错的,快到官方文档也有旧的没更新,前路坑太多. 到发文为止,已经有theano/tensorflow/CNT ...

  7. 超大规模视觉通用感知模型

    超大规模视觉通用感知模型 通用感知模型简介与发展 超大规模图像.文本主干网络 多任务兼容解码网络 参考文献 通用感知模型简介与发展 通用感知模型是指一个模型解决不同的感知任务,应用于各种模态数据. 通 ...

  8. 聚观早报|九安医疗从硅谷银行取回6亿存款;商汤科技发布通用大模型

    今日要闻:九安医疗从硅谷银行取回6亿存款:OpenAI推出GPT-4更精准解决问题:iPhone 14/Plus黄色版开售即破发:消息称英伟达RTX 4070显卡即将上市:商汤科技发布多模态通用大模型 ...

  9. 法国科学家发布AI模型,阐释蛋白结构和功能及进化关系

    https://www.toutiao.com/a6671451084893979143/ 法国科学家最近发布了分析蛋白序列的AI工具,相关研究成果发表在权威杂志eLife (Learning pro ...

最新文章

  1. 【数据结构】单链表的实现(C语言)
  2. 【面向工业界】推荐算法工程师培养计划
  3. 文件及文件夹更改通知/监测软件TheFolderSpy
  4. java 注解 权限_java 使用注解 处理权限(springboot)
  5. Qt Creator建立一个通用项目
  6. 典型的Linux系统启动需要完成的服务
  7. DOM-8 【兼容】冒泡捕获流、事件与事件源对象、事件委托
  8. 超出内容用省略号替代
  9. 再说409,又提离别痛
  10. 创作优质的视频号作品四个方向
  11. 【服务器】Discuz论坛实现微信小程序(修改接口)
  12. 前端学习笔记系列一:2 Vue的单文件组件
  13. JS调用OCX控件过程
  14. playwright基本使用方法
  15. win10计算机加域步骤,关于win10加入域的的详细操作步骤
  16. linux 编译libvlc,libvlc-源码编译流程记录
  17. SQL语句--关于赋值
  18. silverlight java通信_Silverlight使用JavaSocket连接jabber服务器
  19. Origin Pro2017使用PatchOriginPro.exe破解提示Patch unsuccessfully or already
  20. Unity之使用LitJson做游戏存档

热门文章

  1. 牛顿迭代法求数的平方根
  2. 农行:“边缘计算+”技术银行业应用及生态探索
  3. Java实现鼠标右键快捷保存QQ微信截图和复制的文字
  4. python 调试 pdb_python pdb调试
  5. 员工管理系统(练习打卡~)
  6. 卷积神经网络(CNN)——快速导读
  7. python合并excel相同元素的不同数据,python 合并多张excel 处理重复数据
  8. ArcGIS Engine 画扇形要素
  9. Java开发者福音 阿里巴巴宣布连任Java全球管理组织席位
  10. 5G时代的来临,会给我们的生活带来哪些改变