Linux文件系统(六)---三大缓冲区之 目录缓冲区dcache

来源:互联网 发布:手机淘宝邮箱注册链接 编辑:程序博客网 时间:2024/06/04 18:57

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

 (内核:2.4.37)


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

Ps:dentry结构

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. 67 struct dentry {  
  2. 68         atomic_t d_count;  
  3. 69         unsigned int d_flags;  
  4. 70         struct inode  * d_inode;        /* Where the name belongs to - NULL is negative */  
  5. 71         struct dentry * d_parent;       /* parent directory */  
  6. 72         struct list_head d_hash;        /* lookup hash list */  
  7. 73         struct list_head d_lru;         /* d_count = 0 LRU list */  
  8. 74         struct list_head d_child;       /* child of parent list */  
  9. 75         struct list_head d_subdirs;     /* our children */  
  10. 76         struct list_head d_alias;       /* inode alias list */  
  11. 77         int d_mounted;  
  12. 78         struct qstr d_name;  
  13. 79         unsigned long d_time;           /* used by d_revalidate */  
  14. 80         struct dentry_operations  *d_op;  
  15. 81         struct super_block * d_sb;      /* The root of the dentry tree */  
  16. 82         unsigned long d_vfs_flags;  
  17. 83         void * d_fsdata;                /* fs-specific data */  
  18. 84         unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */  
  19. 85 };  

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

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. 52 static struct list_head *dentry_hashtable;  
  2. 53 static LIST_HEAD(dentry_unused);  

哈希链表:从中能够快速获取与给定的文件名和目录名对应的目录项对象。

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


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

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. 1181 static void __init dcache_init(unsigned long mempages)  
  2. 1182 {  
  3. 1183         struct list_head *d;  
  4. 1184         unsigned long order;  
  5. 1185         unsigned int nr_hash;  
  6. 1186         int i;  
  7. 1187   
  8. 1188         /*  
  9. 1189          * A constructor could be added for stable state like the lists, 
  10. 1190          * but it is probably not worth it because of the cache nature 
  11. 1191          * of the dcache.  
  12. 1192          * If fragmentation is too bad then the SLAB_HWCACHE_ALIGN 
  13. 1193          * flag could be removed here, to hint to the allocator that 
  14. 1194          * it should not try to get multiple page regions.   
  15. 1195          */  
  16. 1196         dentry_cache = kmem_cache_create("dentry_cache",  
  17. 1197                                          sizeof(struct dentry),  
  18. 1198                                          0,  
  19. 1199                                          SLAB_HWCACHE_ALIGN,  
  20. 1200                                          NULL, NULL);  
  21. 1201         if (!dentry_cache)  
  22. 1202                 panic("Cannot create dentry cache");  
  23. 1203   
  24. 1204 #if PAGE_SHIFT < 13  
  25. 1205         mempages >>= (13 - PAGE_SHIFT);  
  26. 1206 #endif  
  27. 1207         mempages *= sizeof(struct list_head);  
  28. 1208         for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)  
  29. 1209                 ;  
  30. 1210   
  31. 1211         do {  
  32. 1212                 unsigned long tmp;  
  33. 1213   
  34. 1214                 nr_hash = (1UL << order) * PAGE_SIZE /  
  35. 1215                         sizeof(struct list_head);  
  36. 1216                 d_hash_mask = (nr_hash - 1);  
  37. 1217   
  38. 1218                 tmp = nr_hash;  
  39. 1219                 d_hash_shift = 0;  
  40. 1220                 while ((tmp >>= 1UL) != 0UL)  
  41. 1221                         d_hash_shift++;  
  42. 1222   
  43. 1223                 dentry_hashtable = (struct list_head *)  
  44. 1224                         __get_free_pages(GFP_ATOMIC, order);  
  45. 1225         } while (dentry_hashtable == NULL && --order >= 0);  
  46. 1226   
  47. 1227         printk(KERN_INFO "Dentry cache hash table entries: %d (order: %ld, %ld bytes)\n",  
  48. 1228                         nr_hash, order, (PAGE_SIZE << order));  
  49. 1229   
  50. 1230         if (!dentry_hashtable)  
  51. 1231                 panic("Failed to allocate dcache hash table\n");  
  52. 1232   
  53. 1233         d = dentry_hashtable;  
  54. 1234         i = nr_hash;  
  55. 1235         do {  
  56. 1236                 INIT_LIST_HEAD(d);  
  57. 1237                 d++;  
  58. 1238                 i--;  
  59. 1239         } while (i);  
  60. 1240 }  

上面代码就是相当于分配cache空间,并将hash表什么的都初始化了~~~


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

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. 580 /** 
  2. 581  * d_alloc      -       allocate a dcache entry 
  3. 582  * @parent: parent of entry to allocate 
  4. 583  * @name: qstr of the name 
  5. 584  * 
  6. 585  * Allocates a dentry. It returns %NULL if there is insufficient memory 
  7. 586  * available. On a success the dentry is returned. The name passed in is 
  8. 587  * copied and the copy passed in may be reused after this call. 
  9. 588  */  
  10. 589    
  11. 590 struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)  
  12. 591 {  
  13. 592         char * str;  
  14. 593         struct dentry *dentry;  
  15. 594   
  16. 595         dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);   /* 分配一个dentry空间 */  
  17. 596         if (!dentry)  
  18. 597                 return NULL;  
  19. 598   
  20. 599         if (name->len > DNAME_INLINE_LEN-1) {  
  21. 600                 str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);  
  22. 601                 if (!str) {  
  23. 602                         kmem_cache_free(dentry_cache, dentry);   
  24. 603                         return NULL;  
  25. 604                 }  
  26. 605         } else  
  27. 606                 str = dentry->d_iname;   
  28. 607         /* 复制name */  
  29. 608         memcpy(str, name->name, name->len);  
  30. 609         str[name->len] = 0;  
  31. 610         /* 下面根据dentr的字段进行赋值,具体的字段意义见:http://blog.csdn.net/shanshanpt/article/details/38943731 */  
  32. 611         atomic_set(&dentry->d_count, 1);  
  33. 612         dentry->d_vfs_flags = 0;  
  34. 613         dentry->d_flags = 0;  
  35. 614         dentry->d_inode = NULL;  
  36. 615         dentry->d_parent = NULL;  
  37. 616         dentry->d_sb = NULL;  
  38. 617         dentry->d_name.name = str;  
  39. 618         dentry->d_name.len = name->len;  
  40. 619         dentry->d_name.hash = name->hash;  
  41. 620         dentry->d_op = NULL;  
  42. 621         dentry->d_fsdata = NULL;  
  43. 622         dentry->d_mounted = 0;  
  44. 623         INIT_LIST_HEAD(&dentry->d_hash);  
  45. 624         INIT_LIST_HEAD(&dentry->d_lru);  
  46. 625         INIT_LIST_HEAD(&dentry->d_subdirs);  
  47. 626         INIT_LIST_HEAD(&dentry->d_alias);  
  48. 627         if (parent) {  
  49. 628                 dentry->d_parent = dget(parent);  
  50. 629                 dentry->d_sb = parent->d_sb;  
  51. 630         } else  
  52. 631                 INIT_LIST_HEAD(&dentry->d_child);  
  53. 632   
  54. 633         spin_lock(&dcache_lock);  
  55. 634         if (parent)  
  56. 635                 list_add(&dentry->d_child, &parent->d_subdirs);  
  57. 636         dentry_stat.nr_dentry++;  
  58. 637         spin_unlock(&dcache_lock);  
  59. 638   
  60. 639         return dentry;  
  61. 640 }  
  62. 641   

下面看看怎么去寻找一个目录,涉及函数d_lookup:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. 698 /** 
  2. 699  * d_lookup - search for a dentry 
  3. 700  * @parent: parent dentry 
  4. 701  * @name: qstr of name we wish to find 
  5. 702  * 
  6. 703  * Searches the children of the parent dentry for the name in question. If 
  7. 704  * the dentry is found its reference count is incremented and the dentry 
  8. 705  * is returned. The caller must use d_put to free the entry when it has 
  9. 706  * finished using it. %NULL is returned on failure. 
  10. 707  */  
  11. 708    
  12. 709 struct dentry * d_lookup(struct dentry * parent, struct qstr * name)  
  13. 710 {  
  14. 711         unsigned int len = name->len;  
  15. 712         unsigned int hash = name->hash;  
  16. 713         const unsigned char *str = name->name;  
  17. 714         struct list_head *head = d_hash(parent,hash); /* 通过hash值计算得到目录项缓冲区位置的head */  
  18. 715         struct list_head *tmp;  
  19. 716   
  20. 717         spin_lock(&dcache_lock);  
  21. 718         tmp = head->next;  
  22. 719         for (;;) {   /* 下面循环找到对应的dentry */  
  23. 720                 struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);  
  24. 721                 if (tmp == head)  
  25. 722                         break;  
  26. 723                 tmp = tmp->next;  
  27. 724                 if (dentry->d_name.hash != hash)  
  28. 725                         continue;  
  29. 726                 if (dentry->d_parent != parent)  
  30. 727                         continue;  
  31. 728                 if (parent->d_op && parent->d_op->d_compare) {  
  32. 729                         if (parent->d_op->d_compare(parent, &dentry->d_name, name))  
  33. 730                                 continue;  
  34. 731                 } else {  
  35. 732                         if (dentry->d_name.len != len)  
  36. 733                                 continue;  
  37. 734                         if (memcmp(dentry->d_name.name, str, len))  
  38. 735                                 continue;  
  39. 736                 }  
  40. 737                 __dget_locked(dentry);  
  41. 738                 dentry->d_vfs_flags |= DCACHE_REFERENCED;   /* 找到,那么添加引用就OK */  
  42. 739                 spin_unlock(&dcache_lock);  
  43. 740                 return dentry;     /* 返回找到的dentry。里面有我们需要的信息例如inode */  
  44. 741         }  
  45. 742         spin_unlock(&dcache_lock);  
  46. 743         return NULL;  
  47. 744 }  

其他的代码暂时就不看了,以后总结。。。
0 0