目录项缓存 dentry

blog.csdn.net/jinking01/article/details/105..

《深入Linux内核架构》

由于块设备速度较慢,可能需要很长时间才能找到与一个文件名关联的inode。

比如打开/usr/bin/vim 文件

  • 首先需要去/所在的inode找到/的数据块,从/的数据块中读取到usr这个条目的inode

  • 跳转到user 对应的inode,根据/usr inode 指向的数据块,读取到/usr 目录的内容,从中读取到bin这个条目的inode

  • 跳转到/usr/bin/对应的inode,根据/usr/bin/指向的数据块,从中读取到/usr/bin/目录的内容,从里面找到vim的inode

Linux提供了page cache页高速缓存,很多文件的内容已经缓存在内存里,如果没有dentry,文件名无法快速地关联到inode,即使文件的内容已经缓存在页高速缓存,但是每一次不得不重复地从磁盘上找出来文件名到VFS inode的关联

通过目录项缓存dentry快速访问此前查找的结果。读取一个目录项(目录或文件)的数据之后,会创建一个dentry实例,以缓存找到的数据

COPY

struct dentry { 
        atomic_t d_count; 
        unsigned int d_flags; /* 由d_lock保护 */ 
        spinlock_t d_lock; /* 每个dentry的锁 */ 
        ***struct inode *d_inode***; /* 文件名所属的inode,如果为NULL,则表示不存在的文件名 */ 
        /* 
        * 接下来的3个字段由__d_lookup处理
        * 将它们放置在这里,使之能够装填到一个缓存行中
        */ 
        struct hlist_node d_hash; /* 用于查找的散列表 */ 
        struct dentry *d_parent; /* 父目录的dentry实例 */ 
        ***struct qstr d_name;*** 
        struct list_head d_lru; /* LRU链表 */ 
        union { 
                struct list_head d_child; 
                /* 链表元素,用于将当前dentry连接到父目录dentry的d_subdirs链表中 */ 
                struct rcu_head d_rcu; 
        } d_u; 
        struct list_head d_subdirs; /* 子目录/文件的目录项链表 */ 
        struct list_head d_alias; /* 链表元素,用于将dentry连接到inode的i_dentry链表中 */ 
        unsigned long d_time; /* 由d_revalidate使用 */ 
        struct dentry_operations *d_op; 
        struct super_block *d_sb; /* dentry树的根,超级块 */ 
        void *d_fsdata; /* 特定于文件系统的数据 */ 
        int d_mounted; 
        ***unsigned char d_iname[DNAME_INLINE_LEN_MIN];*** /* 短文件名存储在这里 */ 
};

dentry缓存只包含文件系统结构的一小部分,主要用途是建立文件名和相关的inode之间的关联。

(1) d_inode是指向相关的inode实例的指针。

(2) d_name指定了文件的名称。qstr是一个内核字符串的包装器。它存储了实际的char *字符串 以及字符串长度和散列值,这使得更容易处理查找工作。

这里并不存储绝对路径,只有路径的最后一个分量,例如对/usr/bin/emacs只存储 emacs,因为上述链表结构已经映射了目录结构。

(3) 如果文件名只由少量字符组成,则保存在d_iname中,而不是dname中,以加速访问。