当前位置: 首页 > 工具软件 > DCache > 使用案例 >

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

司徒高丽
2023-12-01

在文件系统中,有三大缓冲为了提升效率: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 }

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

 类似资料: