/*
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中。
后面会通过代码讲解下数据结构之间的关联。