您的位置首页>企业动态>

linux 虚拟文件可以系统实现

导读 大家好,我是极客范的本期栏目编辑小友,现在为大家讲解linux 虚拟文件可以系统实现问题。虚拟文件系统(VFS)是linux内核和特定输入输出设

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解linux 虚拟文件可以系统实现问题。

虚拟文件系统(VFS)是linux内核和特定输入输出设备之间的一层封装的公共访问接口。通过这个接口,linux内核可以以同样的方式访问各种I/O设备。

虚拟文件系统本身是linux内核的一部分,它纯粹是软件,不需要任何硬件支持。

1.虚拟文件系统的作用

虚拟文件系统(VFS)是linux内核和存储设备之间的抽象层,具有以下优点。

-简化的应用程序开发:应用程序通过统一的系统调用访问各种存储介质。

-简化了向内核添加新文件系统的过程:新文件系统只需要实现VFS的接口,内核部分不需要修改。

2.虚拟文件系统的四个主要对象

虚拟文件中有四个主要对象,每个对象的具体含义可以在下面的详细介绍中找到。

2.1超级区块

Super_block主要存储与文件系统相关的信息,这是文件系统级的概念。

它通常存储在磁盘的特定扇区中,但对于那些基于内存的文件系统(如proc、sysfs),超级块在使用时会在内存中创建。

超级块的定义如下:

/* *超级块结构中定义了很多字段,*这里只介绍一些重要的属性*/struct super _ block { structure list _ heads _ list;construct super _ operations * s _ op;struct dentry * s _ root;struct mutex s _ lock;int s _ count;struct list _ head s _ inodes;struct MTD _ info * s _ MTD;fmode _ t _ s _ mode;};/* *超级块的操作方法在s_op *中定义,这里只介绍一些比较重要的函数*/struct super _ operations { struct inode *(alloc _ inode)(struct super _ block * SB);void(* destroy _ inode)(struct inode *);void(* dirty _ inode)(struct inode *);int(* write _ inode)(struct inode *,int);void(* drop _ inode)(structinode *);void(* delete _ inode)(struct inode *);void(* put _ super)(struct super _ block *);void(* write _ super)(struct super _ block *);int (* sync _ fs)更新磁盘上的超级块(structsuper _ block * SB,int wait);int(* statfs)(structurentry *,structkstat fs *);int(* remount _ fs)(struct super _ block *、int *、char *);void(* clear _ inode)(struct inode *);void(* umount _ begin)(structsuper _ block *);};

2.2索引节点

xt-indent: 2em;">索引节点是VFS中的核心概念,它包含内核在操作文件或目录时需要的全部信息。

一个索引节点代表文件系统中的一个文件(这里的文件不仅是指我们平时所认为的普通的文件,还包括目录,特殊设备文件等等)。

索引节点和超级块一样是实际存储在磁盘上的,当被应用程序访问到时才会在内存中创建。

索引节点定义在:

/* * 索引节点结构中定义的字段非常多, * 这里只介绍一些重要的属性 */struct inode { struct hlist_node i_hash; struct list_head i_list; struct list_head i_sb_list; struct list_head i_dentry; unsigned long i_ino; atomic_t i_count; unsigned int i_nlink; uid_t i_uid; gid_t i_gid; struct TImespec i_aTIme; struct TImespec i_mtime; struct timespec i_ctime; const struct inode_operations *i_op; const struct file_operations *i_fop; struct super_block *i_sb; struct address_space *i_mapping; struct address_space i_data; unsigned int i_flags; void *i_private; };/* * 其中的 i_op 中定义了索引节点的操作方法 * 这里只介绍一些相对重要的函数 */struct inode_operations { int (*create) (struct inode *,struct dentry *,int, struct nameidata *); struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); int (*link) (struct dentry *,struct inode *,struct dentry *); void * (*follow_link) (struct dentry *, struct nameidata *); void (*put_link) (struct dentry *, struct nameidata *, void *); void (*truncate) (struct inode *);};

2.3 目录项

和超级块和索引节点不同,目录项并不是实际存在于磁盘上的。

在使用的时候在内存中创建目录项对象,其实通过索引节点已经可以定位到指定的文件,

但是索引节点对象的属性非常多,在查找,比较文件时,直接用索引节点效率不高,所以引入了目录项的概念。

路径中的每个部分都是一个目录项,比如路径: /mnt/cdrom/foo/bar 其中包含5个目录项,/ mnt cdrom foo bar

每个目录项对象都有3种状态:被使用,未使用和负状态

- 被使用:对应一个有效的索引节点,并且该对象由一个或多个使用者

- 未使用:对应一个有效的索引节点,但是VFS当前并没有使用这个目录项

- 负状态:没有对应的有效索引节点(可能索引节点被删除或者路径不存在了)

目录项的目的就是提高文件查找,比较的效率,所以访问过的目录项都会缓存在slab中。

slab中缓存的名称一般就是 dentry,可以通过如下命令查看:

[wangyubin@localhost kernel]$ sudo cat /proc/slabinfo | grep dentrydentry 212545 212625 192 21 1 : tunables 0 0 0 : slabdata 10125 10125 0

目录项定义在:

struct dentry { atomic_t d_count; unsigned int d_flags; spinlock_t d_lock; int d_mounted; struct inode *d_inode; struct hlist_node d_hash; struct dentry *d_parent; struct qstr d_name; struct list_head d_lru; /* * d_child and d_rcu can share memory */ union { struct list_head d_child; struct rcu_head d_rcu; } d_u; struct list_head d_subdirs; struct list_head d_alias; unsigned long d_time; const struct dentry_operations *d_op; struct super_block *d_sb; void *d_fsdata; unsigned char d_iname[DNAME_INLINE_LEN_MIN]; };struct dentry_operations { int (*d_revalidate)(struct dentry *, struct nameidata *); int (*d_hash) (struct dentry *, struct qstr *); int (*d_compare) (struct dentry *, struct qstr *, struct qstr *); int (*d_delete)(struct dentry *); void (*d_release)(struct dentry *); void (*d_iput)(struct dentry *, struct inode *); char *(*d_dname)(struct dentry *, char *, int);};

2.4 文件对象

文件对象表示进程已打开的文件,从用户角度来看,我们在代码中操作的就是一个文件对象。

文件对象反过来指向一个目录项对象(目录项反过来指向一个索引节点)

其实只有目录项对象才表示一个已打开的实际文件,虽然一个文件对应的文件对象不是唯一的,但其对应的索引节点和目录项对象却是唯一的。

文件对象的定义在:

/* * 文件对象结构中定义的字段非常多, * 这里只介绍一些重要的属性 */struct file { union { struct list_head fu_list; struct rcu_head fu_rcuhead; } f_u; struct path f_path; const struct file_operations *f_op; atomic_long_t f_count; };/* * 其中的 f_op 中定义了文件对象的操作方法 * 这里只介绍一些相对重要的函数 */struct file_operations { loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id);};

2.5 四个对象之间关系图

上面分别介绍了4种对象分别的属性和方法,下面用图来展示这4个对象的和VFS之间关系以及4个对象之间的关系。

3. 文件系统相关的数据结构

处理上面4个主要的对象之外,VFS中还有2个专门针对文件系统的2个对象,

- struct file_system_type: 用来描述文件系统的类型(比如ext3,ntfs等等)

- struct vfsmount        : 描述一个安装文件系统的实例

file_system_type 结构体位于:

struct file_system_type { const char *name; int fs_flags; int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; struct list_head fs_supers; struct lock_class_key s_lock_key; struct lock_class_key s_umount_key; struct lock_class_key i_lock_key; struct lock_class_key i_mutex_key; struct lock_class_key i_mutex_dir_key; struct lock_class_key i_alloc_sem_key;};

每种文件系统,不管由多少个实例安装到系统中,还是根本没有安装到系统中,都只有一个 file_system_type 结构。

当文件系统被实际安装时,会在安装点创建一个 vfsmount 结构体。

结构体代表文件系统的实例,也就是文件系统被安装几次,就会创建几个 vfsmount

vfsmount 的定义参见:

struct vfsmount { struct list_head mnt_hash; struct vfsmount *mnt_parent; struct dentry *mnt_mountpoint; struct dentry *mnt_root; struct super_block *mnt_sb; struct list_head mnt_mounts; struct list_head mnt_child; int mnt_flags; const char *mnt_devname; struct list_head mnt_list; struct list_head mnt_expire; struct list_head mnt_share; struct list_head mnt_slave_list; struct list_head mnt_slave; struct vfsmount *mnt_master; struct mnt_namespace *mnt_ns; int mnt_id; int mnt_group_id; /* * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount * to let these frequently modified fields in a separate cache line * (so that reads of mnt_flags wont ping-pong on SMP machines) */ atomic_t mnt_count; int mnt_expiry_mark; int mnt_pinned; int mnt_ghosts; #ifdef CONFIG_SMP int *mnt_writers; #else int mnt_writers; #endif};

4. 进程相关的数据结构

以上介绍的都是在内核角度看到的 VFS 各个结构,所以结构体中包含的属性非常多。

而从进程的角度来看的话,大多数时候并不需要那么多的属性,所有VFS通过以下3个结构体和进程紧密联系在一起。

- struct files_struct  :由进程描述符中的 files 目录项指向,所有与单个进程相关的信息(比如打开的文件和文件描述符)都包含在其中。

- struct fs_struct     :由进程描述符中的 fs 域指向,包含文件系统和进程相关的信息。

- struct mmt_namespace :由进程描述符中的 mmt_namespace 域指向。

struct files_struct 位于:

struct files_struct { atomic_t count; struct fdtable *fdt; struct fdtable fdtab; spinlock_t file_lock ____cacheline_aligned_in_smp; int next_fd; struct embedded_fd_set close_on_exec_init; struct embedded_fd_set open_fds_init; struct file * fd_array[NR_OPEN_DEFAULT]; };

struct fs_struct 位于:

struct fs_struct { int users; rwlock_t lock; int umask; int in_exec; struct path root, pwd; };

struct mmt_namespace 位于:

但是在2.6内核之后似乎没有这个结构体了,而是用 struct nsproxy 来代替。

以下是 struct task_struct 结构体中关于文件系统的3个属性。

struct task_struct 的定义位于:

struct fs_struct *fs; struct files_struct *files; struct nsproxy *nsproxy; 

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。