在文件系统中,有三大缓冲为了提升效率:inode缓冲区、dentry缓冲区、块缓冲。
(内核:2.4.37)
为什么这个缓冲区会存在,不好意思,我说了废话,当然和前面一样的,为了提升效率,例如我们写一个.c的helloworld文件,简单的过程是编辑,编译,执行。。。那么这个过程都是需要找到所在的文件位置的,如果每次都从根开始找并且还有构造相应的目录项对象,是很费时的,所以将目录项一般也都是缓存起来的~~~
Ps:dentry结构
67structdentry {
68 atomic_t d_count;
69 unsigned intd_flags;
70 structinode * d_inode;/* Where the name belongs to - NULL is negative */
71 structdentry * d_parent;/* parent directory */
72 structlist_head d_hash;/* lookup hash list */
73 structlist_head d_lru;/* d_count = 0 LRU list */
74 structlist_head d_child;/* child of parent list */
75 structlist_head d_subdirs;/* our children */
76 structlist_head d_alias;/* inode alias list */
77 intd_mounted;
78 structqstr d_name;
79 unsigned longd_time;/* used by d_revalidate */
80 structdentry_operations *d_op;
81 structsuper_block * d_sb;/* The root of the dentry tree */
82 unsigned longd_vfs_flags;
83 void* d_fsdata;/* fs-specific data */
84 unsigned chard_iname[DNAME_INLINE_LEN];/* small names */
85 };
和前面的一样,这个也涉及到几个相应的链表来管理,那么看看/fs/dcache.c中哪些链表被定义了。
52staticstructlist_head *dentry_hashtable;
53 staticLIST_HEAD(dentry_unused);
哈希链表
:从中能够快速获取与给定的文件名和目录名对应的目录项对象。
“未使用”链表:所有未使用 目录项对象都存放在一个LRU的双向链表。LRU链表的首元素和尾元素的地址存放在变量dentry_unused中的next 域和prev域中。目录项对象的d_lru域包含的指针指向该链表中相邻目录的对象。
简单的看一下dcache初始化过程:
1181staticvoid__init dcache_init(unsignedlongmempages)
1182 {
1183 structlist_head *d;
1184 unsigned longorder;
1185 unsigned intnr_hash;
1186 inti;
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 nature
1191 * of the dcache.
1192 * If fragmentation is too bad then the SLAB_HWCACHE_ALIGN
1193 * flag could be removed here, to hint to the allocator that
1194 * it should not try to get multiple page regions.
1195 */
1196 dentry_cache = kmem_cache_create("dentry_cache",
1197 sizeof(structdentry),
1198 0,
1199 SLAB_HWCACHE_ALIGN,
1200 NULL, NULL);
1201 if(!dentry_cache)
1202 panic("Cannot create dentry cache");
1203
1204 #ifPAGE_SHIFT
1205 mempages >>= (13 - PAGE_SHIFT);
1206 #endif
1207 mempages *= sizeof(structlist_head);
1208 for(order = 0; ((1UL <
1209 ;
1210
1211 do{
1212 unsigned longtmp;
1213
1214 nr_hash = (1UL <
1215 sizeof(structlist_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 = (structlist_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 <
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 entry
582 * @parent: parent of entry to allocate
583 * @name: qstr of the name
584 *
585 * Allocates a dentry. It returns %NULL if there is insufficient memory
586 * available. On a success the dentry is returned. The name passed in is
587 * copied and the copy passed in may be reused after this call.
588 */
589
590 structdentry * d_alloc(structdentry * parent,conststructqstr *name)
591 {
592 char* str;
593 structdentry *dentry;
594
595 dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); /* 分配一个dentry空间 */
596 if(!dentry)
597 returnNULL;
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 returnNULL;
604 }
605 } else
606 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 } else
631 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 returndentry;
640 }
641
下面看看怎么去寻找一个目录,涉及函数d_lookup:
698/**
699 * d_lookup - search for a dentry
700 * @parent: parent dentry
701 * @name: qstr of name we wish to find
702 *
703 * Searches the children of the parent dentry for the name in question. If
704 * the dentry is found its reference count is incremented and the dentry
705 * is returned. The caller must use d_put to free the entry when it has
706 * finished using it. %NULL is returned on failure.
707 */
708
709 structdentry * d_lookup(structdentry * parent,structqstr * name)
710 {
711 unsigned intlen = name->len;
712 unsigned inthash = name->hash;
713 constunsignedchar*str = name->name;
714 structlist_head *head = d_hash(parent,hash);/* 通过hash值计算得到目录项缓冲区位置的head */
715 structlist_head *tmp;
716
717 spin_lock(&dcache_lock);
718 tmp = head->next;
719 for(;;) {/* 下面循环找到对应的dentry */
720 structdentry * dentry = list_entry(tmp,structdentry, 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 returndentry;/* 返回找到的dentry。里面有我们需要的信息例如inode */
741 }
742 spin_unlock(&dcache_lock);
743 returnNULL;
744 }
其他的代码暂时就不看了,以后总结。。。