linux文件系统数据结构

    xiaoxiao2021-03-25  136

    /* super_block 超级块对象,存储文件系统的信息,通常对应于存放在磁盘特定扇区的 文件系统超级块或者文件系统控制块。 */ struct super_block { struct list_head s_list; /* 所有超级块链表 */ dev_t s_dev; /* 设备标识符 */ unsigned char s_blocksize_bits; //位标书的block的大小 unsigned long s_blocksize; //以字节为单位每个block 大小 loff_t s_maxbytes; //单个文件最大的字节数 struct file_system_type *s_type; //文件系统类型 const struct super_operations *s_op; //超级块操作集 const struct dquot_operations *dq_op;//磁盘配额方法 const struct quotactl_ops *s_qcop;//限额控制方法 const struct export_operations *s_export_op;//导出方法 unsigned long s_flags;//挂载标志 unsigned long s_magic; struct dentry *s_root;//目录挂载点 struct rw_semaphore s_umount;//卸载信号量 int s_count;//超级块引用计数 atomic_t s_active;//活动引用计数 #ifdef CONFIG_SECURITY void                    *s_security; #endif const struct xattr_handler **s_xattr; //扩展的属性操作 struct list_head s_inodes; /* 超级块的所有inode链表 */ struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */ struct list_head s_mounts; /* list of mounts; _not_ for fs use */ /* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */ struct list_head s_dentry_lru; /* unused dentry lru */ int s_nr_dentry_unused; /* # of dentry on lru */ /* s_inode_lru_lock protects s_inode_lru and s_nr_inodes_unused */ spinlock_t s_inode_lru_lock ____cacheline_aligned_in_smp; struct list_head s_inode_lru; /* unused inode lru */ int s_nr_inodes_unused; /* # of inodes on lru */ struct block_device *s_bdev; //相关的块设备 struct backing_dev_info *s_bdi; struct mtd_info *s_mtd;  struct hlist_node s_instances; struct quota_info s_dquot; /* Diskquota specific options */ struct sb_writers s_writers; char s_id[32]; /* Informational name */ u8 s_uuid[16]; /* UUID */ void *s_fs_info; /* Filesystem private info */ unsigned int s_max_links; fmode_t s_mode; /* Granularity of c/m/atime in ns.   Cannot be worse than a second */ u32   s_time_gran; /* * The next field is for VFS *only*. No filesystems have any business * even looking at it. You had been warned. */ struct mutex s_vfs_rename_mutex; /* Kludge */ /* * Filesystem subtype.  If non-empty the filesystem type field * in /proc/mounts will be "type.subtype" */ char *s_subtype; /* * Saved mount options for lazy filesystems using * generic_show_options() */ char __rcu *s_options; const struct dentry_operations *s_d_op; /* default d_op for dentries */ /* * Saved pool identifier for cleancache (-1 means none) */ int cleancache_poolid; struct shrinker s_shrink; /* 超级块在内存回收时的处理操作 */ /* Number of inodes with nlink == 0 but still referenced */ atomic_long_t s_remove_count; /* Being remounted read-only */ int s_readonly_remount; }; /* 索引节点,描述文件的属性信息,unix风格文件系统,索引节点要从磁盘上读取 */ struct inode { umode_t i_mode; //访问权限 unsigned short i_opflags; kuid_t i_uid;//user id kgid_t i_gid;//group id 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;//inode 操作集 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;//inode字节数 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 */ struct hlist_node i_hash;//inode 链接的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; const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ struct file_lock *i_flock; struct address_space i_data; #ifdef CONFIG_QUOTA struct dquot *i_dquot[MAXQUOTAS]; #endif 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 #ifdef CONFIG_IMA atomic_t i_readcount; /* struct files open RO */ #endif void *i_private; /* fs or device private pointer */ }; /* 目录项,磁盘上并不存在,主要是为了文件树的查找操作,动态创建保存在内存中的 */ struct dentry { /* RCU lookup touched fields */ unsigned int d_flags; /* 目录项标示 */ seqcount_t d_seq; /* per dentry seqlock */ struct hlist_bl_node d_hash; /* lookup hash list */ struct dentry *d_parent; /* 父目录的目录项 */ struct qstr d_name; struct inode *d_inode; //目录项对应的inode unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ /* Ref lookup also touches following */ unsigned int d_count; /* protected by d_lock */ spinlock_t d_lock; /* per dentry lock */ const struct dentry_operations *d_op; struct super_block *d_sb; /* 文件的超级块*/ 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; }; /* 文件对象,表示进程已打开的文件,即已打开的文件在内存中的表示, 同一个文件可能被多个进程打开,所以存在多个文件对象。 */ struct file { union { struct llist_node fu_llist; //文件对象链表 struct rcu_head fu_rcuhead;// } f_u; struct path f_path; #define f_dentry f_path.dentry//文件路径 struct inode *f_inode;//文件对应的inode const struct file_operations *f_op; //文件操作 /* * Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR. * Must not be taken from IRQ context. */ spinlock_t f_lock;//文件锁 atomic_long_t f_count;//文件对象使用计数 unsigned int f_flags;//打开文件时指定的标志 fmode_t f_mode;//文件的访问模式 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; #ifdef CONFIG_DEBUG_WRITECOUNT unsigned long f_mnt_write_state; #endif }; /* 对整个OS而言,用于描述各种特定的文件系统 */ struct file_system_type { const char *name; //文件系统名字 int fs_flags; //文件系统类型标志 #define FS_REQUIRES_DEV 1 //文件系统必须在物理设备上 #define FS_BINARY_MOUNTDATA 2 //mount此文件系统时需要使用二进制数据结构的mount data #define FS_HAS_SUBTYPE 4 //文件系统含有子类型,最常见的就是FUSE,FUSE本是不是真正的文件系统,所以要通过子文件系统类型来区别通过FUSE接口实现的不同文件系统 #define FS_USERNS_MOUNT 8 /* 文件系统每次挂载后都是不同的user namespace,如用于devpts  */ #define FS_USERNS_DEV_MOUNT 16 /*  user namespace挂载支持MNT_DEV, 即非nodev模式  */ #define FS_RENAME_DOES_D_MOVE 32768 /*重命名操作reame()直接按照移动操作d_move()来处理,主要用于网络万件系统 */   struct dentry *(*mount) (struct file_system_type *, int,       const char *, void *); //挂载文件系统时调用 void (*kill_sb) (struct super_block *);//删除内存中的super block,在卸载文件系统时使用 struct module *owner; //指向实现这个文件系统的模块,通常为THIS_MODULE宏 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; }; /* 文件系统挂载点信息,其实就是有挂载点根目录项和super block组成 */ struct vfsmount { struct dentry *mnt_root; /* root of the mounted tree */ struct super_block *mnt_sb; /* pointer to superblock */ int mnt_flags; }; 和进程相关的数据结构files_struct,fs_struct,namespace struct task_struct { .... /* filesystem information */ struct fs_struct *fs; /* open file information */ struct files_struct *files; /* namespaces */ struct nsproxy *nsproxy; } 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; }; struct files_struct {   /*    * read mostly part    */ atomic_t count; //结构的使用计数 struct fdtable __rcu *fdt; struct fdtable fdtab; //fd表   /*    * written part on a separate cache line in SMP    */ spinlock_t file_lock ____cacheline_aligned_in_smp; //文件锁 int next_fd; //下一个可用的fd unsigned long close_on_exec_init[1]; //exec时关闭的文件描述符链表 unsigned long open_fds_init[1]; //打开的文件描述符链表 struct file __rcu * fd_array[NR_OPEN_DEFAULT]; //文件对象数组 }; 进程打开的文件先放到fd_array中,存放不下的时候内核动态申请存储空间,fdt指向 新申请的空间,用来保存打开的文件信息。 //进程的文件信息 struct fs_struct { int users; spinlock_t lock; seqcount_t seq; int umask; int in_exec; //当前正在执行的文件 struct path root, pwd; //进程根目录和当前工作目录 }; //进程的文件系统命名空间 struct mnt_namespace { atomic_t count; //结构体引用计数 unsigned int proc_inum; struct mount * root; struct list_head list; struct user_namespace *user_ns; u64 seq; /* Sequence number to prevent loops */ wait_queue_head_t poll; int event; }; //结构体表示一个文件系统的mount实例  struct mount {           struct hlist_node mnt_hash;     /* 用于链接到全局 mount_hashtable */           struct mount *mnt_parent;       /* 指向此文件系统的挂载点所属的文件系统,即父文件系统 */           struct dentry *mnt_mountpoint;  /* 指向此文件系统的挂载点的dentry */           struct vfsmount mnt;            /* 指向此文件系统的vfsmount实例 */           struct rcu_head mnt_rcu;        /* 用于rcu锁 */   #ifdef CONFIG_SMP           struct mnt_pcp __percpu *mnt_pcp; /* 用于多核 */   #else           int mnt_count;                  /* 使用计数 */           int mnt_writers;                   #endif           struct list_head mnt_mounts;  /* 挂载在此文件系统下的所有子文件系统的链表的表头,下面的节点都是mnt_child*/           struct list_head mnt_child;     /* 链接到被此文件系统所挂的父文件系统的mnt_mounts上 */           struct list_head mnt_instance;  /* 链接到sb->s_mounts上的一个mount实例 */           const char *mnt_devname;        /* 设备名,如 /dev/dsk/hda1 */           struct list_head mnt_list;      /* 链接到进程namespace中已挂载文件系统中,表头为mnt_namespace的list域 */           struct list_head mnt_expire;    /* 链接到一些文件系统专有的过期链表,如NFS, CIFS等 */           struct list_head mnt_share;     /* 链接到共享挂载的循环链表中 */           struct list_head mnt_slave_list;/* 此文件系统的slave mount链表的表头 */           struct list_head mnt_slave;     /* 连接到master文件系统的mnt_slave_list */           struct mount *mnt_master;       /* 指向此文件系统的master文件系统,slave is on master->mnt_slave_list */           struct mnt_namespace *mnt_ns;   /* 指向包含这个文件系统的进程的name space */           struct mountpoint *mnt_mp;      /* where is it mounted */   #ifdef CONFIG_FSNOTIFY           struct hlist_head mnt_fsnotify_marks;           __u32 mnt_fsnotify_mask;   #endif           int mnt_id;                     /* mount identifier */           int mnt_group_id;               /* peer group identifier */           int mnt_expiry_mark;            /* 如果为1,表示此文件系统已过期 */           int mnt_pinned;           struct path mnt_ex_mountpoint;   }   //mount实例对外传递的信息   struct vfsmount {           struct dentry *mnt_root;        /* 指向这个文件系统的根目录的dentry 比如/mnt这样的结构 */           struct super_block *mnt_sb;     /* 此挂载实例超级块对象 */           int mnt_flags;                  /* 此文件系统的挂载标志 */   }   综上,文件系统的数据结构其实也是分层的结构。 首先OS会从全局角度注册file_system_type,每一种文件系统类型从上往下有超级块,inode, 为了便于文件查找虚拟了dentry结构。最后每种文件系统通过挂载之后才能访问, 每次挂载就会产生一个挂载实例struct mount加入mount_hashtable中。 后面会通过代码讲解下数据结构之间的关联。
    转载请注明原文地址: https://ju.6miu.com/read-6087.html

    最新回复(0)