Linux虚拟文件系统(VFS)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux虚拟文件系统(VFS)相关的知识,希望对你有一定的参考价值。

1.虚拟文件系统(VFS)

1.1 VFS的情景

虚拟文件系统主要是对文件进行抽象的模型,可以把文件模型当面向对象的方式区看待

通用的文件模型对象组成

  • 超级块(superblock)
  • 索引节点(inode)
  • 目录项(dentry)
  • 文件(file)

超级块:主要是用来描述文件系统信息,一般一个次哦按都会分成很多个块,可以理解成一个磁盘上是很多superblock组成.

索引节点inode:描述文件的相关信息,每一个文件都会对应一个唯一的inode

目录项:每个文件除了有一个inode外,还有对应的一个目录项,目录项和索引节点的区别在于,索引节点是代表真实的物理意义上的文件,记录的是物理上相关属性,而目录项dentry描述的是文件逻辑上的属性,稍后指出在内核文件系统的相关定义可能就会比较清楚

文件:file是内核文件内部的一个定义,主要是和文件相关的操作属性有关系(例如:open/read/write等操作)

superblock在内核的相关属性结构

struct super_block 
	struct list_head	s_list;		/* Keep this first */
	kdev_t			s_dev;
	unsigned long		s_blocksize;
	unsigned char		s_blocksize_bits;
	unsigned char		s_lock;
	unsigned char		s_dirt;
	struct file_system_type	*s_type;
	struct super_operations	*s_op;
	struct dquot_operations	*dq_op;
	unsigned long		s_flags;
	unsigned long		s_magic;
	struct dentry		*s_root;
	wait_queue_head_t	s_wait;

	struct list_head	s_dirty;	/* dirty inodes */
	struct list_head	s_files;

	struct block_device	*s_bdev;
	struct list_head	s_mounts;	/* vfsmount(s) of this one */
	struct quota_mount_options s_dquot;	/* Diskquota specific options */

	union 
		struct minix_sb_info	minix_sb;
		struct ext2_sb_info	ext2_sb;
		struct hpfs_sb_info	hpfs_sb;
		struct ntfs_sb_info	ntfs_sb;
		struct msdos_sb_info	msdos_sb;
		struct isofs_sb_info	isofs_sb;
		struct nfs_sb_info	nfs_sb;
		struct sysv_sb_info	sysv_sb;
		struct affs_sb_info	affs_sb;
		struct ufs_sb_info	ufs_sb;
		struct efs_sb_info	efs_sb;
		struct shmem_sb_info	shmem_sb;
		struct romfs_sb_info	romfs_sb;
		struct smb_sb_info	smbfs_sb;
		struct hfs_sb_info	hfs_sb;
		struct adfs_sb_info	adfs_sb;
		struct qnx4_sb_info	qnx4_sb;
		struct bfs_sb_info	bfs_sb;
		struct udf_sb_info	udf_sb;
		struct ncp_sb_info	ncpfs_sb;
		struct usbdev_sb_info   usbdevfs_sb;
		void			*generic_sbp;
	 u;
	/*
	 * The next field is for VFS *only*. No filesystems have any business
	 * even looking at it. You had been warned.
	 */
	struct semaphore s_vfs_rename_sem;	/* Kludge */

	/* The next field is used by knfsd when converting a (inode number based)
	 * file handle into a dentry. As it builds a path in the dcache tree from
	 * the bottom up, there may for a time be a subpath of dentrys which is not
	 * connected to the main tree.  This semaphore ensure that there is only ever
	 * one such free path per filesystem.  Note that unconnected files (or other
	 * non-directories) are allowed, but not unconnected diretories.
	 */
	struct semaphore s_nfsd_free_path_sem;
;

inode结构属性定义,会发现每一个inode会保护一个super_block结构,所以每次对inode的操作就可以对磁盘上的向文件进行操作,里面包含一个比较重要的结构就是file_operation结构

struct inode 
	struct list_head	i_hash;
	struct list_head	i_list;
	struct list_head	i_dentry;
	
	struct list_head	i_dirty_buffers;

	unsigned long		i_ino;
	atomic_t		i_count;
	kdev_t			i_dev;
	umode_t			i_mode;
	nlink_t			i_nlink;
	uid_t			i_uid;
	gid_t			i_gid;
	kdev_t			i_rdev;
	loff_t			i_size;
	time_t			i_atime;
	time_t			i_mtime;
	time_t			i_ctime;
	unsigned long		i_blksize;
	unsigned long		i_blocks;
	unsigned long		i_version;
	struct semaphore	i_sem;
	struct semaphore	i_zombie;
	struct inode_operations	*i_op;
	struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
	struct super_block	*i_sb;
	wait_queue_head_t	i_wait;
	struct file_lock	*i_flock;
	struct address_space	*i_mapping;
	struct address_space	i_data;	
	struct dquot		*i_dquot[MAXQUOTAS];
	struct pipe_inode_info	*i_pipe;
	struct block_device	*i_bdev;

	unsigned long		i_dnotify_mask; /* Directory notify events */
	struct dnotify_struct	*i_dnotify; /* for directory notifications */

	unsigned long		i_state;

	unsigned int		i_flags;
	unsigned char		i_sock;

	atomic_t		i_writecount;
	unsigned int		i_attr_flags;
	__u32			i_generation;
	union 
		struct minix_inode_info		minix_i;
		struct ext2_inode_info		ext2_i;
		struct hpfs_inode_info		hpfs_i;
		struct ntfs_inode_info		ntfs_i;
		struct msdos_inode_info		msdos_i;
		struct umsdos_inode_info	umsdos_i;
		struct iso_inode_info		isofs_i;
		struct nfs_inode_info		nfs_i;
		struct sysv_inode_info		sysv_i;
		struct affs_inode_info		affs_i;
		struct ufs_inode_info		ufs_i;
		struct efs_inode_info		efs_i;
		struct romfs_inode_info		romfs_i;
		struct shmem_inode_info		shmem_i;
		struct coda_inode_info		coda_i;
		struct smb_inode_info		smbfs_i;
		struct hfs_inode_info		hfs_i;
		struct adfs_inode_info		adfs_i;
		struct qnx4_inode_info		qnx4_i;
		struct bfs_inode_info		bfs_i;
		struct udf_inode_info		udf_i;
		struct ncp_inode_info		ncpfs_i;
		struct proc_inode_info		proc_i;
		struct socket			socket_i;
		struct usbdev_inode_info        usbdev_i;
		void				*generic_ip;
	 u;
;

目录项dentry结构

truct dentry 
	atomic_t d_count;
	unsigned int d_flags;
	struct inode  * d_inode;	/* Where the name belongs to - NULL is negative */
	struct dentry * d_parent;	/* parent directory */
	struct list_head d_vfsmnt;
	struct list_head d_hash;	/* lookup hash list */
	struct list_head d_lru;		/* d_count = 0 LRU list */
	struct list_head d_child;	/* child of parent list */
	struct list_head d_subdirs;	/* our children */
	struct list_head d_alias;	/* inode alias list */
	struct qstr d_name;
	unsigned long d_time;		/* used by d_revalidate */
	struct dentry_operations  *d_op;
	struct super_block * d_sb;	/* The root of the dentry tree */
	unsigned long d_reftime;	/* last time referenced */
	void * d_fsdata;		/* fs-specific data */
	unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
;

file结构,比较重要结构,涉及到相关文件的操作file_operations

struct file 
	struct list_head	f_list;
	struct dentry		*f_dentry;
	struct vfsmount         *f_vfsmnt;
	struct file_operations	*f_op;
	atomic_t		f_count;
	unsigned int 		f_flags;
	mode_t			f_mode;
	loff_t			f_pos;
	unsigned long 		f_reada, f_ramax, f_raend, f_ralen, f_rawin;
	struct fown_struct	f_owner;
	unsigned int		f_uid, f_gid;
	int			f_error;

	unsigned long		f_version;

	/* needed for tty driver, and maybe others */
	void			*private_data;
;

1.2 内核文件相关函数

应用程序打开文件相关函数

int open(const char *pathname, int flags, mode_t mode);
asmlinkage long sys_open(const char * filename, int flags, int mode)

	char * tmp;
	int fd, error;

#if BITS_PER_LONG != 32
	flags |= O_LARGEFILE;
#endif
	tmp = getname(filename);
	fd = PTR_ERR(tmp);
	if (!IS_ERR(tmp)) 
        // 获取分配文件fd
		fd = get_unused_fd();
		if (fd >= 0) 
            // 调用内核filp_open代开文件,返回一个file结构
			struct file *f = filp_open(tmp, flags, mode);
			error = PTR_ERR(f);
			if (IS_ERR(f))
				goto out_error;
			fd_install(fd, f);
		
out:
		putname(tmp);
	
	return fd;

out_error:
	put_unused_fd(fd);
	fd = error;
	goto out;

struct file *filp_open(const char * filename, int flags, int mode)

	int namei_flags, error;
	struct nameidata nd;

	namei_flags = flags;
	if ((namei_flags+1) & O_ACCMODE)
		namei_flags++;
	if (namei_flags & O_TRUNC)
		namei_flags |= 2;
	// 内部主要是对路径及文件inode等进行设置
	error = open_namei(filename, namei_flags, mode, &nd);
	if (!error)
        // 内部主要进行dentry相关结构属性的设置
		return dentry_open(nd.dentry, nd.mnt, flags);

	return ERR_PTR(error);

struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)

文件系统内容还是比较多,列出了一部分,但是其他也是类似的流程,可能内部还涉及到很多细节,后续再搞吧

  • 应用都会通过sys_call进入内核,操作文件系统的相关属性
  • 对文件的操作基本上就是对inode,dentry,file等结构操作

以上是关于Linux虚拟文件系统(VFS)的主要内容,如果未能解决你的问题,请参考以下文章

[搬运工]VFS虚拟文件系统

linux内核源码分析之虚拟文件系统VFS

虚拟文件系统(VFS)

linux文件系统体系结构 和 虚拟文件系统(VFS)

Linux内核虚拟文件系统

linux内核源码分析之虚拟文件系统VFS