目录项对象

from:目录项对象


我们知道VFS把每个目录看作由若干子目录和文件组成的一个普通文件。然而,一旦目录项被读入内存,VFS就把它转换成基于dentry结构的一个目录项对象,该结构的代码如下:

<include/linux/dcache.h>



struct dentry {
    atomic_t     d_count;
    unsigned int d_flags;
    spinlock_t   d_lock;
    int          d_mounted;
    struct inode *d_inode;
    struct hlist_node d_hash;
    struct dentry *d_parent;
    struct qstr d_name;

    struct list_head d_lru;
    union {
        struct list_head d_child;
        struct rcu_head d_rcu;
    } d_u;
    struct list_head d_subdirs;
    struct list_head d_alias;
    unsigned long d_time;
    const struct dentry_operations *d_op;
    struct super_block *d_sb;
    void *d_fsdata;
    unsigned char d_iname[DNAME_INLINE_LEN_MIN];
};


其中目录项对象的字段如下:

字段说明
d_count目录项对象引用计数器
d_flag目录项高速缓存标志
d_lock保护目录项对象的自旋锁
d_inode与文件名关联的索引节点
d_parent父目录的目录项对象
d_name文件名
d_lru用于未使用目录项链表的指针
d_child对目录而言,用于同一父母路中的目录项链表的指针
d_subdirs对目录而言,子目录链表的头
d_alias用于与统一索引节点(别名)相关的目录项链表的指针
d_time由d_revalidate方法使用
d_op目录项方法
d_sb文件的超级块对象
d_fsdata依赖于文件系统的数据
d_rcu回收目录项时由RCU描述符使用
d_cookie指向内核配置文件使用的数据结构的指针
d_hash指向散列表表项链表的指针
d_mounted对目录而言,用于记录安装该目录项的文件系统数的计数器
d_iname存放短文件名的空间

每个目录项可以处于以下四种状态:

  1. 空闲状态。

  2. 未使用状态。

  3. 正在使用状态。

  4. 负状态。

空闲状态

处于该状态的目录项对象不包括有效信息,而且还没有被VFS使用,对应的内存区由slab分配器进行处理。

未使用状态

处于该状态的目录项对象当前还没有被内核使用。该对象的引用计数器d_count的值未0,但其i_node字段仍然指向关联的索引节点。该目录项对象包含有效信息,但为了在必要时回收内存,它的内容可能被丢弃。

正在使用状态

处于该状态的目录项对象当前正在被内核使用,该对象的引用计数器d_count的值未正数,其d_inode字段指向关联的索引节点对象。该目录项对象包含有效的信息,并且不能被丢弃。

负状态

与目录项关联的索引节点不存在,那是因为相应的磁盘索引节点已被删除,或者因为目录项对象时通过解析一个不存在的文件的路径名创建的。目录项对象的d_inode字段设置为NULL,但该对象仍然被保存在目录项高速缓存中,以便后续对统一文件目录名的查找操作能够快速完成1

与目录项对象关联的方法称为目录项操作,这些方法由dentry_operations结构描述,该结构的地址放在目录项对象的d_op字段中。代码如下:

<include/linux/dcache.h>



struct dentry_operations {
    int (*d_revalidate)(struct dentry *, struct nameidata *);
    int (*d_hash) (struct dentry *, struct qstr *);
    int (*d_compare) (
        struct dentry *, struct qstr *, struct qstr *);
    int (*d_delete)(struct dentry *);
    void (*d_release)(struct dentry *);
    void (*d_iput)(struct dentry *, struct inode *);
    char *(*d_dname)(struct dentry *, char *, int);
};

函数名说明
d_revalidate(dentry, nameidate)在把目录项对象转换为一个文件路径名之前,判定该目录项对象是否仍然有效。缺省的VFS函数什么也不做,而网络文件系统可以指定自己的函数
d_hash(dentry, name)生成一个散列值,这是用于目录项散列表、特定于具体文件系统的散列函数
d_compare(dir, name1, name2)比较两个文件名
d_delete(dentry)当对目录项对象的最后一个引用被删除,调用该方法,缺省的VFS函数什么也不做
d_release(dentry)当要释放一个目录项对象时,调用该方法
d_input(dentry, ino)当一个目录对象变为『负』状态时,调用该方法

  1. 负状态这个名词容易使人误解,因为根本不涉及任何负值。