1

总体架构图

clipboard.png
clipboard.png

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]; 
};

clipboard.png

struct fdtable

文件描述符表

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
};

shiyang6017
158 声望59 粉丝