目录项(dentry)定义于 include/linux/dcache.h

目录项对象描述了文件系统的层次结构,一个路径的各个组成部分,不管是目录(VFS将目录当作文件处理),还是普通文件,都是一个目录项对象。

目录项将路径中的每个部分与其对应的inode相联系,一旦VFS得到了所需要的dentry,同时便也得到了相应的inode,即可对文件做想要的操作。沿着路径各部分的目录项进行搜索,最终可找到目标文件的inode

struct dentry {
    /* RCU lookup touched fields */
    unsigned int d_flags;           /* protected by d_lock */
    seqcount_t d_seq;               /* per dentry seqlock */
    struct hlist_bl_node d_hash;    /* lookup hash list */
    struct dentry *d_parent;        /* parent directory */
    struct qstr d_name;
    struct inode *d_inode;
    /* Where the name belongs to - NULL is
     * negative */
    unsigned char d_iname[DNAME_INLINE_LEN];        /* small names */
    /* Ref lookup also touches following */
    struct lockref d_lockref;       /* per-dentry lock and refcount */
    const struct dentry_operations *d_op;
    struct super_block *d_sb;       /* The root of the dentry tree */
    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;
};

每个dentry可能处于以下四个状态:

  • 空闲状态(free)。处于该状态的dentry不包含有效的信息,且没有被VFS使用。
  • 未使用状态(unused)。处于该状态的dentry当前没有被VFS使用,他的引用计数d_count为0,但其d_inodei字段仍然指 向相关连的indoe。这种dentry仍然是一个有效的目录项对象,包含有效的信息,且被保留在内存中以便需要时使用。但是如果需要回收内存时,它们可 能被丢弃。
  • 使用状态(in use)。处于该状态的dentry存在一个或多个使用(d_count为正值),它的d_inode字段指向相关联的inode。这种dentry不能被丢弃。
  • 负状态(negative)。处于该状态的dentry没有对应有效的inode,即它的d_inode字段为NULL, 这是由于其相关联的inode已经被删除,或者它是通过解析一个不存在的文件路径而创建的,但是该对象仍然保留在目录项高速缓存中,以便后续使用。
struct dentry_operations {
    int (*d_revalidate)(struct dentry *, unsigned int);
    int (*d_weak_revalidate)(struct dentry *, unsigned int);
    int (*d_hash)(const struct dentry *, struct qstr *);
    int (*d_compare)(const struct dentry *, const struct dentry *,
                     unsigned int, const char *, const struct qstr *);
    int (*d_delete)(const struct dentry *);
    void (*d_release)(struct dentry *);
    void (*d_prune)(struct dentry *);
    void (*d_iput)(struct dentry *, struct inode *);
    char *(*d_dname)(struct dentry *, char *, int);
    struct vfsmount *(*d_automount)(struct path *);
    int (*d_manage)(struct dentry *, bool);
    struct inode *(*d_select_inode)(struct dentry *, unsigned);
};