在VFS里,目录本身也是一个文件,只是有点特殊。每个文件都有一个dentry(可能不止一个),这个dentry链接到上级目录的dentry。根目录有一个dentry结构,而根目录里的文件和目录都链接到这个根dentry,二级目录里的文件和目录,同样通过dentry链接到二级目录。这样一层层链接,就形成了一颗dentry树。从树顶可以遍历整个文件系统的所有目录和文件。
为了加快对dentry的查找,内核使用了hash表来缓存dentry,称为dentry cache。dentry cache在后面的分析中经常用到,因为dentry的查找一般都先在dentry cache里进行查找。
dentry的结构定义同样很庞杂,和超级块类似,我们当前只分析最重要的部分。dentry结构简化后的定义如代码清单所示。
点击(此处)折叠或打开
-
struct dentry {
-
atomic_t d_count;
-
unsigned int d_flags; /* protected by d_lock */
-
spinlock_t d_lock; /* per dentry lock */
-
int d_mounted; /* obsolete, ->d_flags is now used for this */
-
struct inode *d_inode; /* Where the name belongs to - NULL is
-
* negative */
-
/*
-
* 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; /* lookup hash list */
-
struct dentry *d_parent; /* parent directory */
-
struct qstr d_name;
-
-
struct list_head d_lru; /* LRU list */
-
/*
-
* d_child and d_rcu can share memory
-
*/
-
union {
-
struct list_head d_child; /* child of parent list */
-
struct rcu_head d_rcu;
-
} d_u;
-
struct list_head d_subdirs; /* our children */
-
struct list_head d_alias; /* inode alias list */
-
unsigned long d_time; /* used by d_revalidate */
-
const struct dentry_operations *d_op;
-
struct super_block *d_sb; /* The root of the dentry tree */
-
void *d_fsdata; /* fs-specific data */
-
-
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
- };
d_inode指向一个inode结构。这个inode和dentry共同描述了一个普通文件或者目录文件。
dentry结构里有d_subdirs成员和d_child成员。d_subdirs是子项(子项可能是目录,也可能是文件)的链表头,所有的子项都要链接到这个链表。d_child是dentry自身的链表头,需要链接到父dentry的d_subdirs成员。当移动文件的时候,需要把一个dentry结构从旧的父dentry的链表上脱离,然后链接到新的父dentry的d_subdirs成员。这样dentry结构之间就构成了一颗目录树
d_parent是指针,指向父dentry结构。
d_hash是链接到dentry cache的hash链表。
d_name成员保存的是文件或者目录的名字。打开一个文件的时候,根据这个成员和用户输入的名字比较来搜寻目标文件。
d_mounted 用来指示dentry是否是一个挂载点。如果是挂载点,该成员不为零。