Linux内核数据结构映射-idr(转) linux内核的idr学习(一)

原文:https://blog.csdn.net/m0_37128231/article/details/96727068?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

参考链接:

linux idr机制  https://blog.csdn.net/Morphad/article/details/9051261?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

linux内核IDR机制详解(一)https://blog.csdn.net/weixin_37867857/article/details/85028303?depth_1-utm_source=distribute.pc_relevant.none-task

linux内核的idr学习(一)          https://www.cnblogs.com/zero-jh/p/5184836.html

映射是实现(key,value)绑定的一种数据结构。也称为关联数组。可以视为由唯一key组成的集合。每个key对应这一个value。

常规的映射实现有hash表和二叉树,以及二叉树的变种。

差异
hash表具有相对较好的平均时间复杂度。二叉树有着更好的最坏时间复杂度。

hash表通过hash函数能够映射不同类型的key。二叉树没有hash,更多用于同类key。

hash表中的key经过hash之后是无序的,便于点查找(linkedhashmap是又加了一个指针)。二叉树能够满足顺序保证,便于范围查找。

另外从内存上来说,hash表有效数据的内存占比较小,它的收缩操作太过于浪费时间,不收缩只扩展的话,太浪费内存。

二叉树在内存上释放和扩展有着天然独特的优势。

idr
idr:是用于将uid和一个数据地址进行绑定的一种映射。文件路径为: include/linux/idr.h

由于uid的特殊性:组成元素在固定范围内。相比较于寻常的二叉树,基数树(Redix)显然更适合。

idr中有两个数据结构:idr 和idr_layer

idr数据结构类似于list_head。用于管理idr整个树的信息。其中最关键的是top。它指向了根节点的idr_layer。

struct idr {                    
    struct idr_layer __rcu    *hint;      /* the last layer allocated from */
    struct idr_layer __rcu    *top;       // idr的顶层(根节点)
    int            layers;                /* only valid w/o concurrent changes */
    int            cur;                   /* current pos for cyclic allocation */
    spinlock_t        lock;                
    int            id_free_cnt;            
    struct idr_layer    *id_free;        
};
idr_layer就是每个树中每个节点的数据结构。每个节点有256个指针数组(在64位中,IDR_BITS=8),还有一个槽位图。槽位图是用于快速查找那些指针数组已经被使用。它是由256个bit组成。第x个指针数组被使用,那么第x个bit就被置1。

每个指针数组指向下一层idr_layer。下一层的idr_layer也有一个指针指向它的父节点。

struct idr_layer {
int prefix; /* the ID prefix of this idr_layer */
int layer; /* 第几层 distance from leaf */
struct idr_layer __rcu *ary[1<<IDR_BITS]; /* IDR_BITS = 8 该层有256个指针,指向256个idr_layer*/
int count; /* When zero, we can release it */
union {
/* A zero bit means "space here" */
DECLARE_BITMAP(bitmap, IDR_SIZE); /* 槽位图 */
struct rcu_head rcu_head;
};
};
所以idr数据结构的图示为:(只用了两层作为举例)。每层的arry的下标对应着uid的数值组成。

第一句经过arry[1]、array[2]。所以uid1,也就是映射中的key1为0x0102,value1是一个指向My love for you,a little more than yesterday,这段文字的指针。

第二句经过arry[255]、array[0]。所以uid2,也就是映射中的key2为0xff00,value2是一个指向a little less than tomorrow.这段文字的指针。

所以 string=&Lookup(uid1)+&Lookuo(uid2)。得到string为

My love for you,a little more than yesterday,a little less than tomorrow。



猜你喜欢

转载自www.cnblogs.com/lh03061238/p/12416398.html