第 8 章 虚拟文件系统(4)

目录

8.3 VFS结构

8.3.5 目录项缓存


本专栏文章将有70篇左右,欢迎+关注,查看后续文章。

8.3 VFS结构

8.3.5 目录项缓存

struct dentry:即目录项。

        作用:缓存文件名对应的 inode。加快文件查找。

如果通过文件名查找 inode,很耗时。所以当读取一个目录项(目录或文件)后,会创建 dentry 实例,并缓存查找到路径。

目录项缓存:dentry cache,简称dcache。

不管文件夹,目录还是文件,都可用一个目录项表示。

        如:打开文件 /etc/init.d/lte.sh 后,/、etc、init.d、lte.sh 都有一个 struct dentry 实例。

内核只保存常用的目录和文件对应的 struct dentry。

每个dentry对象有四种状态:

        空闲:该 dentry 不包含有效信息,没有被 VFS 使用。

        未使用:没有被内核使用,即 d_count 为0,但 d_inode 指向对应 inode。

        正使用:d_count 大于0,d_inode 指向对应 inode。

        负状态:不存在对应 inode,相应磁盘索引节点已删除。

1. struct dentry结构体

struct dentry {         //1. 父子链表         2. 关联 inode和文件名d_flags

        unsigned int                    d_flags;

        struct hlist_bl_node         d_hash;

                //用于连接全局哈希表 dentry_hashtable 中冲突项。

                        //dentry_hashtable:包含系统所有struct dentry。

        struct dentry         *d_parent;

                //父目录的 dentry(若为根目录,则指向自身dentry)

        struct qstr            d_name;

                //文件名称,如 /usr/bin/vim 中的vim, 而 /usr/bin 包含在d_child。

                //struct qstr:包含了文件名及其hash值。(比较hash值来简化查找)

      

          struct inode         *d_inode;

                //d_name 文件对应的 inode,文件名不存在则为 NULL,用于查找不存在的文件。

        

        unsigned char         d_iname[16];

                // 短文件名,若文件名小于32字节则使用 d_iname,而不是 d_name。

     

        unsigned int         d_count;                         //引用计数。

        struct dentry_operations         *d_op;         // 文件系统需实现。

        struct super_block                   *d_sb;         //所属超级块。

        unsigned long                         d_time; 

        void                                         *d_fsdata;    //文件系统私有数据。

        union {

                struct list_head            d_lru;

                        // 用于连接到超级块的 s_dentry_lru 链表,即最近未使用的目录项。

                wait_queue_head_t      *d_wait; 

        };

        struct list_head         d_child;         // 用于连接到父目录 dentry 的 d_subdirs 中。

        struct list_head         d_subdirs;     // 包含的子目录。

        union {

                struct hlist_node             d_alias;

                        //用于连接到struct inode中的i_dentry中。

                        //一个inode可有多个dentry。比如硬链接。

                struct hlist_bl_node         d_in_lookup_hash;

                struct rcu_head                d_rcu;

        } d_u;

}

成员介绍:

d_flags:

        1. DCACHE_DISCONNECTED:

                该dentry没有连接到super_block的dentry树。

        2. DCACHE_UNHASHED:

                该dentry没有包含在任何inode hash表。

        3. DCACHE_REFERENCED:

                该dentry最近使用,不被回收。

同一文件的所有 dentry 都通过 d_alias 域挂入该文件inode中的 i_dentry 队列。

注:进程多次打开同一文件,将生成多个struct file,但只有一个struct dentry。

2. 缓存的组织

dentry 目的:加速VFS处理。

一个 dentry 在内存的两种组织:

        1. 全局散列表:

                即 dentry_hashtable:包含所有 dentry 对象。

                        dentry 的 d_hash 用于确定散列冲突位置。

        2. LRU链表:

                若 dentry 的 d_count 为0则加入 LRU 链表。若太老则从内存删除。

                        list_add(&dentry->d_lru,     &dentry->d_sb->s_dentry_lru);

3. dentry操作

struct    dentry_operations {

        int         (*d_revalidate)(struct dentry *, unsigned int);

                //被网络文件系统使用。用于确保一致性,使某些dentry过时。

        int         (*d_weak_revalidate)(struct dentry *, unsigned int);

        int         (*d_hash)(const struct dentry *, struct qstr *);

                //计算dentry的hash值。将其放入dentry hash表。

        int         (*d_compare)(const struct dentry *,const struct qstr *);

                //比较文件名,不同文件系统可自定义是否区分大小写。

        void         (*d_prune)(struct dentry *);

        void         (*d_iput)(struct dentry *, struct inode *);

                //将inode引用计数减1,并释放inode。

        int         (*d_delete)(const struct dentry *);

                //当dentry的d_count为0,用该函数删除dentry。默认为NULL。

        void         (*d_release)(struct dentry *);

                //默认为NULL。

        char         *(*d_dname)(struct dentry *, char *, int);

        int         (*d_manage)(const struct path *, bool);

        struct vfsmount         *(*d_automount)(struct path *);

};

4. 标准函数

struct dentry         *dget(struct dentry *dentry)

        作用:dentry 的 d_count + 1 (引用计数加 1 )。

struct dentry         *dput(struct dentry *dentry)

        作用:

                1. dentry 的 d_count - 1。

                2. 若 d_count 为0,则调用 dentry->d_op->d_delete(dentry);

void         d_drop(struct dentry *dentry)

作用:

        1. 将 dentry 从全局散列表中删除。

        2. 若 d_count 为0,可被 dput 函数调用。

void         d_instantiate(struct dentry *entry, struct inode *inode);

        作用:

                1. 关联一个 dentry 和一个 inode。

                2. 将 dentry->d_inode 连接到 inode->i_dentry 链表。

void         d_add(struct dentry *entry, struct inode *inode)

        作用:

                1. 调用 d_instantiate。

                2. 将 dentry 加入全局散列表。

struct dentry         *d_alloc(struct dentry * parent, struct qstr *name)

        作用:

                1. 分配一个dentry内存,并初始化。

        2. 将dentry加入到 parent->d_subdirs 链表中。

struct dentry         *d_alloc_anon(struct super_block *sb)

        作用:

                1. 分配一个 dentry 内存。

                2. 将dentry加入两个链表:super_block->s_anon ,inode->i_dentry。

struct dentry         *d_lookup(const struct dentry *parent, struct qstr *name)

        作用:在指定目录 parent 中,搜索文件名为 name 的 dentry。

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山下小童

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值