整体架构图
fs_struct
struct fs_struct { atomic_t count; //共享这个表的进程个数 rwlock_t lock; //用于表中字段的读/写自旋锁 int umask; // 当打开文件设置文件权限时所使用的位掩码 struct dentry *root, //根目录的目录项 *pwd, //当前工做目录的目录项 *altroot; // struct vfsmount *rootmnt, //根目录所安装的文件系统对象 *pwdmnt, // 当前工做目录所安装的文件系统对象 *altrootmnt; //模拟根目录的目录项(在 80x86 结构上始终为 NULL) };
struct files_struct
#define NR_OPEN_DEFAULT BITS_PER_LONG #define BITS_PER_LONG 32 /* asm-i386 */ struct files_struct { atomic_t count; // fdtable 就是 APUE第3章 所说的文件描述符表`,fdt初始值指向fdtab 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地址的数组, 当打开文件数量大于32时,须要构造更多该类型的数组 struct file * fd_array[NR_OPEN_DEFAULT]; };
struct fdtable
文件描述符表
node
struct fdtable { unsigned int max_fds; int max_fdset; struct file ** fd; /* current fd array */ fd_set *close_on_exec; // FD_CLOEXEC标志 fd_set *open_fds; //当前打开的文件 struct rcu_head rcu; struct files_struct *free_files; struct fdtable *next; };
struct file
文件对象
数组
/*顺序打乱,突出重点*/ struct file { /* * fu_list becomes invalid after file_free is called and queued via fu_rcuhead for RCU freeing */ union { struct list_head fu_list; struct rcu_head fu_rcuhead; } f_u; /* 用于通用文件对象链表的指针 */ struct dentry *f_dentry; /* 与文件相关的目录项对象 */ mode_t f_mode; /* 进程的访问模式 */ unsigned int f_flags; /* 当打开文件时所指定的标志 */ loff_t f_pos; /* 当前的文件位移量(文件指针) */ atomic_t f_count; /* 文件对象的引用计数器 */ struct vfsmount *f_vfsmnt; /* 含有该文件的已安装文件系统 */ const struct file_operations *f_op; /* 指向文件操做表的指针 */ struct fown_struct f_owner; /* 经过信号进行 I/O 事件通知的数据 */ unsigned int f_uid, f_gid; /* 用户的 UID、 GID */ struct file_ra_state f_ra; /* 文件预读状态 */ unsigned long f_version; /* 版本号,每次使用后自动递增 */ void *f_security; /* 指向文件对象的安全结构的指针 */ /* 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; /* 文件的事件轮询等待者链表的头 */ spinlock_t f_ep_lock; /* 保护 f_ep_links 链表的自旋锁 */ #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping; /* 指向文件地址空间对象的指针 */ };
struct dentry
每一个目录看做由若干子目录和文件组成的一个普通文件。
然而目录项不一样,一旦目录项被读入内存, VFS 就把它转换成基于dentry结构的一个目录项对象。
对于进程查找的路径名中的每一个份量,内核都为其建立一个目录项对象;
缓存
struct dentry { atomic_t d_count; /* 目录项对象引用计数器 */ unsigned int d_flags; /* 目录项高速缓存标志 */ spinlock_t d_lock; /* 保护目录项对象的自旋锁 */ struct inode *d_inode; /* 与文件名关联的索引节点*/ struct qstr d_name; /* 文件名 */ struct list_head d_subdirs; /* 对目录而言,子目录项链表的头 */ /* The next three fields are touched by __d_lookup. Place them here * so they all fit in a cache line. */ struct hlist_node d_hash; /* 指向散列表表项链表的指针 */ struct dentry *d_parent; /* 父目录的目录项对象 */ struct list_head d_lru; /* 用于未使用目录项链表的指针 */ /* * d_child and d_rcu can share memory */ union { struct list_head d_child; /* 对目录而言,用于同一父目录中的目录项链表的指针 */ struct rcu_head d_rcu; /* 回收目录项对象时,由 RCU 描述符使用 */ } d_u; struct list_head d_alias; /* 用于与同一索引节点(别名)相关的目录项链表的指针 */ unsigned long d_time; /* 由 d_revalidate 方法使用 */ struct dentry_operations *d_op; /* 目录项方法 */ struct super_block *d_sb; /* 文件的超级块对象 */ void *d_fsdata; /* 依赖于文件系统的数据 */ void *d_extra_attributes; /* TUX-specific data */ #ifdef CONFIG_PROFILING struct dcookie_struct *d_cookie; /* cookie,指向内核配置文件使用的数据结构的指针*/ #endif int d_mounted; /* 对目录而言,用于记录安装该目录项的文件系统数的计数器 */ unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* 存放短文件名的空间 */ };
struct node
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; /* 引用计数器 */ umode_t i_mode; /* 文件类型与访问权限 */ unsigned int i_nlink; /* 硬连接数目 */ loff_t i_size; /* 文件的字节数 */ uid_t i_uid; /* 全部者标识符 */ gid_t i_gid; /* 全部者组标识符 */ dev_t i_rdev; /* 实设备标识符 */ struct timespec i_atime; /* 上次访问文件的时间 */ struct timespec i_mtime; /* 上次写文件的时间 */ struct timespec i_ctime; /* 上次修改索引节点的时间 */ unsigned int i_blkbits; /* 块的位数 */ unsigned long i_version; /* 版本号(每次使用后自动递增) */ blkcnt_t i_blocks; /* 文件的块数 */ unsigned short i_bytes; /* 文件中最后一个块的字节数 */ spinlock_t i_lock; /* 保护索引节点一些字段的自旋锁: i_blocks, i_bytes, maybe i_size */ struct mutex i_mutex; /* 索引节点信号量 */ struct rw_semaphore i_alloc_sem; /* 在直接 I/O 文件操做中避免出现竞争条件的读/写信号量 */ struct inode_operations *i_op; /* 索引节点的操做 */ const struct file_operations *i_fop; /* 缺省文件操做: former->i_op->default_file_ops */ struct super_block *i_sb; /* 指向超级块对象的指针 */ struct file_lock *i_flock; /* 指向文件锁链表的指针 */ struct address_space *i_mapping; /* 指向缓存 address_space 对象的指针 */ struct address_space i_data; /* 嵌入在 inode 中的文件的 address_space 对象 */ #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; /* 指向字符设备驱动程序的指针 */ }; int i_cindex; /* 拥有一组次设备号的设备文件的索引 */ __u32 i_generation; /* 索引节点版本号(由某些文件系统使用) */ #ifdef CONFIG_DNOTIFY unsigned long i_dnotify_mask; /* 目录通知事件的位掩码 */ struct dnotify_struct *i_dnotify; /* 用于目录通知 */ #endif #ifdef CONFIG_INOTIFY struct list_head inotify_watches; /* watches on this inode */ struct mutex inotify_mutex; /* protects the watches list */ #endif unsigned long i_state; /* 索引节点的状态标志 */ unsigned long dirtied_when; /* 索引节点的弄脏时间(以节拍为单位) */ unsigned int i_flags; /* 文件系统的安装标志 */ atomic_t i_writecount; /* 用于写进程的引用计数器 */ void *i_security; /* 指向索引节点安全结构的指针 */ void *i_private; /* 指向私有数据的指针 */ #ifdef __NEED_I_SIZE_ORDERED seqcount_t i_size_seqcount;/* SMP 系统为 i_size 字段获取一致值时使用的顺序计数器 */ #endif };