博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux文件系统(六)---三大缓冲区之 目录缓冲区dcache
阅读量:4055 次
发布时间:2019-05-25

本文共 8226 字,大约阅读时间需要 27 分钟。

在文件系统中,有三大缓冲为了提升效率:inode缓冲区、dentry缓冲区、块缓冲。

 (内核:2.4.37)

为什么这个缓冲区会存在,不好意思,我说了废话,当然和前面一样的,为了提升效率,例如我们写一个.c的helloworld文件,简单的过程是编辑,编译,执行。。。那么这个过程都是需要找到所在的文件位置的,如果每次都从根开始找并且还有构造相应的目录项对象,是很费时的,所以将目录项一般也都是缓存起来的~~~

Ps:dentry结构

67 struct dentry { 68         atomic_t d_count; 69         unsigned int d_flags; 70         struct inode  * d_inode;        /* Where the name belongs to - NULL is negative */ 71         struct dentry * d_parent;       /* parent directory */ 72         struct list_head d_hash;        /* lookup hash list */ 73         struct list_head d_lru;         /* d_count = 0 LRU list */ 74         struct list_head d_child;       /* child of parent list */ 75         struct list_head d_subdirs;     /* our children */ 76         struct list_head d_alias;       /* inode alias list */ 77         int d_mounted; 78         struct qstr d_name; 79         unsigned long d_time;           /* used by d_revalidate */ 80         struct dentry_operations  *d_op; 81         struct super_block * d_sb;      /* The root of the dentry tree */ 82         unsigned long d_vfs_flags; 83         void * d_fsdata;                /* fs-specific data */ 84         unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ 85 };

和前面的一样,这个也涉及到几个相应的链表来管理,那么看看/fs/dcache.c中哪些链表被定义了。

52 static struct list_head *dentry_hashtable; 53 static LIST_HEAD(dentry_unused);
哈希链表:从中能够快速获取与给定的文件名和目录名对应的目录项对象。

“未使用”链表:所有未使用 目录项对象都存放在一个LRU的双向链表。LRU链表的首元素和尾元素的地址存放在变量dentry_unused中的next 域和prev域中。目录项对象的d_lru域包含的指针指向该链表中相邻目录的对象。

简单的看一下dcache初始化过程:

1181 static void __init dcache_init(unsigned long mempages)1182 {1183         struct list_head *d;1184         unsigned long order;1185         unsigned int nr_hash;1186         int i;1187 1188         /* 1189          * A constructor could be added for stable state like the lists,1190          * but it is probably not worth it because of the cache nature1191          * of the dcache. 1192          * If fragmentation is too bad then the SLAB_HWCACHE_ALIGN1193          * flag could be removed here, to hint to the allocator that1194          * it should not try to get multiple page regions.  1195          */1196         dentry_cache = kmem_cache_create("dentry_cache",1197                                          sizeof(struct dentry),1198                                          0,1199                                          SLAB_HWCACHE_ALIGN,1200                                          NULL, NULL);1201         if (!dentry_cache)1202                 panic("Cannot create dentry cache");1203 1204 #if PAGE_SHIFT < 131205         mempages >>= (13 - PAGE_SHIFT);1206 #endif1207         mempages *= sizeof(struct list_head);1208         for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)1209                 ;1210 1211         do {1212                 unsigned long tmp;1213 1214                 nr_hash = (1UL << order) * PAGE_SIZE /1215                         sizeof(struct list_head);1216                 d_hash_mask = (nr_hash - 1);1217 1218                 tmp = nr_hash;1219                 d_hash_shift = 0;1220                 while ((tmp >>= 1UL) != 0UL)1221                         d_hash_shift++;1222 1223                 dentry_hashtable = (struct list_head *)1224                         __get_free_pages(GFP_ATOMIC, order);1225         } while (dentry_hashtable == NULL && --order >= 0);1226 1227         printk(KERN_INFO "Dentry cache hash table entries: %d (order: %ld, %ld bytes)\n",1228                         nr_hash, order, (PAGE_SIZE << order));1229 1230         if (!dentry_hashtable)1231                 panic("Failed to allocate dcache hash table\n");1232 1233         d = dentry_hashtable;1234         i = nr_hash;1235         do {1236                 INIT_LIST_HEAD(d);1237                 d++;1238                 i--;1239         } while (i);1240 }
上面代码就是相当于分配cache空间,并将hash表什么的都初始化了~~~

下面看一下怎么分配一个目录项对象,涉及函数d_alloc:

580 /**581  * d_alloc      -       allocate a dcache entry582  * @parent: parent of entry to allocate583  * @name: qstr of the name584  *585  * Allocates a dentry. It returns %NULL if there is insufficient memory586  * available. On a success the dentry is returned. The name passed in is587  * copied and the copy passed in may be reused after this call.588  */589  590 struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)591 {592         char * str;593         struct dentry *dentry;594 595         dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);   /* 分配一个dentry空间 */596         if (!dentry)597                 return NULL;598 599         if (name->len > DNAME_INLINE_LEN-1) {600                 str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);601                 if (!str) {602                         kmem_cache_free(dentry_cache, dentry); 603                         return NULL;604                 }605         } else606                 str = dentry->d_iname; 607         /* 复制name */608         memcpy(str, name->name, name->len);609         str[name->len] = 0;610         /* 下面根据dentr的字段进行赋值,具体的字段意义见:http://blog.csdn.net/shanshanpt/article/details/38943731 */611         atomic_set(&dentry->d_count, 1);612         dentry->d_vfs_flags = 0;613         dentry->d_flags = 0;614         dentry->d_inode = NULL;615         dentry->d_parent = NULL;616         dentry->d_sb = NULL;617         dentry->d_name.name = str;618         dentry->d_name.len = name->len;619         dentry->d_name.hash = name->hash;620         dentry->d_op = NULL;621         dentry->d_fsdata = NULL;622         dentry->d_mounted = 0;623         INIT_LIST_HEAD(&dentry->d_hash);624         INIT_LIST_HEAD(&dentry->d_lru);625         INIT_LIST_HEAD(&dentry->d_subdirs);626         INIT_LIST_HEAD(&dentry->d_alias);627         if (parent) {628                 dentry->d_parent = dget(parent);629                 dentry->d_sb = parent->d_sb;630         } else631                 INIT_LIST_HEAD(&dentry->d_child);632 633         spin_lock(&dcache_lock);634         if (parent)635                 list_add(&dentry->d_child, &parent->d_subdirs);636         dentry_stat.nr_dentry++;637         spin_unlock(&dcache_lock);638 639         return dentry;640 }641
下面看看怎么去寻找一个目录,涉及函数d_lookup:

698 /**699  * d_lookup - search for a dentry700  * @parent: parent dentry701  * @name: qstr of name we wish to find702  *703  * Searches the children of the parent dentry for the name in question. If704  * the dentry is found its reference count is incremented and the dentry705  * is returned. The caller must use d_put to free the entry when it has706  * finished using it. %NULL is returned on failure.707  */708  709 struct dentry * d_lookup(struct dentry * parent, struct qstr * name)710 {711         unsigned int len = name->len;712         unsigned int hash = name->hash;713         const unsigned char *str = name->name;714         struct list_head *head = d_hash(parent,hash); /* 通过hash值计算得到目录项缓冲区位置的head */715         struct list_head *tmp;716 717         spin_lock(&dcache_lock);718         tmp = head->next;719         for (;;) {   /* 下面循环找到对应的dentry */720                 struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);721                 if (tmp == head)722                         break;723                 tmp = tmp->next;724                 if (dentry->d_name.hash != hash)725                         continue;726                 if (dentry->d_parent != parent)727                         continue;728                 if (parent->d_op && parent->d_op->d_compare) {729                         if (parent->d_op->d_compare(parent, &dentry->d_name, name))730                                 continue;731                 } else {732                         if (dentry->d_name.len != len)733                                 continue;734                         if (memcmp(dentry->d_name.name, str, len))735                                 continue;736                 }737                 __dget_locked(dentry);738                 dentry->d_vfs_flags |= DCACHE_REFERENCED;   /* 找到,那么添加引用就OK */739                 spin_unlock(&dcache_lock);740                 return dentry;     /* 返回找到的dentry。里面有我们需要的信息例如inode */741         }742         spin_unlock(&dcache_lock);743         return NULL;744 }
其他的代码暂时就不看了,以后总结。。。

你可能感兴趣的文章
hdu 1561 The more, The Better (树形背包dp)
查看>>
【设计模式】学习笔记14:状态模式(State)
查看>>
poj 1976 A Mini Locomotive (dp 二维01背包)
查看>>
斯坦福大学机器学习——因子分析(Factor analysis)
查看>>
项目导入时报错:The import javax.servlet.http.HttpServletRequest cannot be resolved
查看>>
不一定会执行finally代码块的两个例子
查看>>
LRUCache
查看>>
linux对于没有写权限的文件如何保存退出vim
查看>>
Windows下安装ElasticSearch6.3.1以及ElasticSearch6.3.1的Head插件
查看>>
IntelliJ IDEA 下的svn配置及使用的非常详细的图文总结
查看>>
【IntelliJ IDEA】idea导入项目只显示项目中的文件,不显示项目结构
查看>>
itellij idea导入web项目并部署到tomcat
查看>>
ssh 如何方便的切换到其他节点??
查看>>
JSP中文乱码总结
查看>>
AspectJ下载和安装
查看>>
Java-IO-File类
查看>>
Java-IO-java的IO流
查看>>
Java-IO-字节流和字符流
查看>>
Java-IO-输入/输出流体系
查看>>
Java实现DES加密解密
查看>>