VFS虚拟文件系统

基本概念

超级块对象

磁盘文件系统会包含有一个超级块,该块用于保存磁盘文件系统的一些属性和信息,内核设计了超级块对象用于描述超级块信息,超级块对象是存在于内存中的,超级块存在于磁盘上,因此需要定期同步。

文件索引节点对象

磁盘文件系统是按照文件节点inode来管理文件的,内核中使用文件节点对象来管理文件节点inode。文件节点对象存在于内存中,而其中的一些数据需要和磁盘中保持同步。

目录项对象

磁盘文件系统会按照自己的方式管理和保存目录项,它存在的目的是管理文件系统中的文件名以及目录结构,一个目录项对应一个文件节点,而一个文件节点则可能对应多个目录项,比如硬链接就是这样。内核中使用目录项对象来管理目录项,目录项对象中的内容需要和磁盘目录项保持同步。

文件对象

文件对象是内核用于描述进程如何与打开的文件进行交互操作的,它的结构体是struct file,它只存在于内存中,而在磁盘文件系统中不存在,使用文件对象可以找到对应的目录项对象,从而找到文件节点对象,并最终和物理磁盘联系在一起。每个进程都有自己创建的的文件对象集合用于记录当前进程打开的文件,每个文件对象都对应着一个目录项对象,而一个目录项对象可能对应着多个文件对象,比如当一个文件同时被两个进程打开时,每个进程都有一个该文件对应的文件对象,里面保存着当前的文件指针偏移量,而这两个文件对象实际上对应着同一个目录项。

文件描述符

每个进程都对应各自的文件管理结构struct files_struct,这个结构体管理着所有被进程打开和使用的文件对象指针,文件对象指针存放在一个数组结构中,而数组的下标就是文件描述符。多个描述符可能对应同一个文件对象。

对应关系

多个文件描述符可能对应着同一个文件对象(dup操作),多个文件对象可能对应着一个文件目录项(多进程同时打开一个文件),多个文件目录项可能对应着一个文件索引节点(硬链接,硬链接是共享同一个inode,软链接不会)。

VFS(虚拟文件系统)

Linux支持多种不同类型的文件系统,为了保证统一的对上接口和一致性,内核实现了虚拟文件系统来达到这个目的,内核把各种类型的文件系统抽象为统一的模型,把它叫做虚拟文件系统。

相关的结构体

进程相关的files_struct结构体:

 /*
  * Open file table structure
  */
 struct files_struct {
   /*
    * read mostly part
    */
     atomic_t count;
     struct fdtable __rcu *fdt;
     struct fdtable fdtab;
   /*
    * written part on a separate cache line in SMP
    */
     spinlock_t file_lock ____cacheline_aligned_in_smp;
     int next_fd;
     unsigned long close_on_exec_init[1];
     unsigned long open_fds_init[1];
     struct file __rcu * fd_array[NR_OPEN_DEFAULT];
 };

struct fdtable {
    unsigned int max_fds;
    struct file __rcu **fd;      /* current fd array */
    unsigned long *close_on_exec;
    unsigned long *open_fds;
    struct rcu_head rcu;
};  

fdtable中的fd初始化时指向的就是当前进程的fd array数组,NR_OPEN_DEFAULT等于32。在初始化时该成员是直接指向进程的fd_array数组的,后面如果进程打开文件数量超过此值,那么会进行expand扩展操作。

struct files_struct init_files = {
    .count      = ATOMIC_INIT(1),
    .fdt        = &init_files.fdtab,
    .fdtab      = {
        .max_fds    = NR_OPEN_DEFAULT,
        .fd     = &init_files.fd_array[0],
        .close_on_exec  = init_files.close_on_exec_init,
        .open_fds   = init_files.open_fds_init,
    },
    .file_lock  = __SPIN_LOCK_UNLOCKED(init_files.file_lock),
};

默认的NR_OPEN_DEFAULT是32个,所以默认对应的open_fds和close_on_exec位图都是32bit的。
进程相关的fs_struct结构体:

struct fs_struct {
    int users;
    spinlock_t lock;
    seqcount_t seq;
    int umask;
    int in_exec;
    struct path root, pwd;
};

管理着当前进程的pwd当前路径,以及所在文件系统的root路径。路径包含的内容如下:

struct path {
    struct vfsmount *mnt;
    struct dentry *dentry;
};

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_ACL
	struct posix_acl	*i_acl;
	struct posix_acl	*i_default_acl;
#endif

	const struct inode_operations	*i_op;
	struct super_block	*i_sb;
	struct address_space	*i_mapping;

#ifdef CONFIG_SECURITY
	void			*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;
	blkcnt_t		i_blocks;

#ifdef __NEED_I_SIZE_ORDERED
	seqcount_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_wb_list;	/* backing dev IO list */
	struct 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_IMA
	atomic_t		i_readcount; /* struct files open RO */
#endif
	const 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;
	};

	__u32			i_generation;

#ifdef CONFIG_FSNOTIFY
	__u32			i_fsnotify_mask; /* all events this inode cares about */
	struct hlist_head	i_fsnotify_marks;
#endif

	void			*i_private; /* fs or device private pointer */
};

dentry目录结构体如下所示:

struct dentry { 
    /* RCU lookup touched fields */
    unsigned int d_flags;       /* protected by d_lock */
    seqcount_t d_seq;       /* per dentry seqlock */
    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通过d_inode成员和inode联系在一起的。

file结构体如下所示:

struct file {
    union {
        struct llist_node   fu_llist;
        struct rcu_head     fu_rcuhead;
    } f_u;
    struct path     f_path;
    struct inode        *f_inode;   /* cached value */
    const struct file_operations    *f_op;

    /*
     * Protects f_ep_links, f_flags.
     * Must not be taken from IRQ context.
     */
    spinlock_t      f_lock;
    atomic_long_t       f_count;
    unsigned int        f_flags;
    fmode_t         f_mode;
    struct mutex        f_pos_lock;
    loff_t          f_pos;
    struct fown_struct  f_owner;
    const struct cred   *f_cred;
    struct file_ra_state    f_ra;

    u64         f_version;
#ifdef CONFIG_SECURITY
    void            *f_security;
#endif
    /* needed for tty driver, and maybe others */
    void            *private_data;

#ifdef CONFIG_EPOLL
    /* Used by fs/eventpoll.c to link all the hooks to this file */
    struct list_head    f_ep_links;
    struct list_head    f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
    struct address_space    *f_mapping;
} __attribute__((aligned(4)));  /* lest something weird decides that 2 is OK */


file结构体通过path成员f_path与对应的dentry联系在一起。

filename结构体用来记录一个路径名称,其中包含audit_names进行相关的审计。

struct filename {
    const char      *name;  /* pointer to actual string */
    const __user char   *uptr;  /* original userland pointer */
    struct audit_names  *aname;
    int         refcnt;
    bool            separate; /* should "name" be freed? */
};

nameidata是用来在中间操作的结构体,包含dentry和inode相关的信息。

struct nameidata {
    struct path path;
    struct qstr last;
    struct path root;
    struct inode    *inode; /* path.dentry.d_inode */
    unsigned int    flags;
    unsigned    seq, m_seq;
    int     last_type;
    unsigned    depth;
    struct file *base;
    char *saved_names[MAX_NESTED_LINKS + 1];
};

关系框图如下:
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值