Date:2019-6-19
主要转载自:
https://www.cnblogs.com/mingziday/p/3969269.html
https://blog.csdn.net/qq_22613757/article/details/91049293
https://blog.csdn.net/joker0910/article/details/8250085

由于原博比较混乱,这里单独整理一下排版:

一、概述

Linux radix树最广泛的用途是用于内存管理,结构address_space通过radix树跟踪绑定到地址映射上的核心页,该radix树允许内存管理代码快速查找标识为dirty或writeback的页。Linux radix树的API函数在lib/radix-tree.c中实现。

Linux基数树(radix tree)是将指针与long整数键值相关联的机制,它存储有效率,并且可快速查询,用于指针与整数值的映射(如:IDR机制)、内存管理等。

上图显示了一个有3级结点的radix树,每个数据条目(item)可用3个6位的键值(key)进行索引,键值从左到右分别代表第1~3层结点位置。没有孩子的结点在图中不出现。因此,radix树为稀疏树提供了有效的存储,代替固定尺寸数组提供了键值到指针的快速查找。

以index=0x5BFB68为例,化为二进制,每6位为一组:10110(22,第一层编号) 111111(63第二次编号) 101101(45第三层编号) 101000(40第四层编号)

二、基本数据结构

struct radix_tree_root {unsigned int height;gfp_t gfp_mask;struct radix_tree_node *rnode;/*间接指针指向结点而非数据条目,通过设置root->rnode的低位表示是否是间指针*/
};struct radix_tree_node {unsigned int height; /* 从叶子向上计算的树高度 */ unsigned int count; /*非叶子结点含有一个count域,表示出现在该结点的孩子的数量*/struct rcu_head rcu_head;void *slots[RADIX_TREE_MAP_SIZE]; //64个指针,每层64个子节点unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];//2X2数组,每个成员都为32位,//在结点结构radix_tree_node中,tags域是一个二维数组,每个slot用2位标识,这是一个典型的用空间换时间的应用。tags域用于记录该结点下面的子结点有没有相应的标志位。//结点标签数组=每个slot需要的最大标签位数*slot数所需的long类型变量数 /*tag[0]64位,2个long类型,每一位代表一个slot,表示其PG_dirtytag[0]64位,2个long类型,每一位代表一个slot,表示其PG_Writeback如果当前节点的tags[0]值为1,那么它的子树节点就存在PAGE_CACHE_DIRTY节点,否则这个子树分枝就不存在着这样的节点,就不必再查找这个子树了。比如在查找PG_dirty的页面时,就不需要遍历整个树,而可以跳过那些tags[0]为0值的子树,这样就提高了查找效率*/
};

三、全局定义

#define RADIX_TREE_MAP_SHIFT 6
/*值为6时,表示每个结点有2^6=64个slot,值为4时,表示有2^4=16个slot*/
#define RADIX_TREE_MAP_SIZE (1UL <<RADIX_TREE_MAP_SHIFT) //1000000,2^6=64
/*表示1个叶子结点可映射的页数,如:1<<6=64,表示可映射64个slot映射64页*/
#define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1) //111111
#define RADIX_TREE_TAG_LONGS \
((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) /BITS_PER_LONG) //(64+32-1)/32=2
#define RADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsignedlong)) //32
#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \
RADIX_TREE_MAP_SHIFT)) //(32+6-1)/6=6
#define RADIX_TREE_MAX_TAGS 2
/*定义slot数占用的long类型长度个数,每个slot用位图1位进行标记,如:64个slot时,值为2*/static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH + 1]
// 全局数组,在32位机器上,这个数组大小是7,表示每一层的最大有多少个slot
height=0:maxindex=0, 第一层只有一个radix_tree_node
height=1:maxindex=2^6-1, 第二层最多63个
height=2:maxindex=2^12-1,
height=3:maxindex=2^18-1,
height=4:maxindex=2^24-1, 若每个slot为4k,则表示支持64G
height=5:maxindex=2^30-1,
height=6:maxindex=2^32-1, 16T

四、初始化函数

与初始化radix tree有关的函数有三个,尚不清楚他们之间的相互关系以及该调用谁

//初始化一个名字是name的树根。mask是gfp相关的掩码,在内存管理的时候用到。
#define RADIX_TREE(name, mask) struct radix_tree_root name = RADIX_TREE_INIT(mask)
#define RADIX_TREE_INIT(mask)   {.height = 0,.gfp_mask = (mask),.rnode = NULL,
}#define INIT_RADIX_TREE(root, mask)
do {(root)->height = 0;(root)->gfp_mask = (mask);(root)->rnode = NULL;
} while (0)void __init radix_tree_init(void)
{
radix_tree_node_cachep = kmem_cache_create("radix_tree_node",sizeof(struct radix_tree_node), 0,SLAB_PANIC | SLAB_RECLAIM_ACCOUNT,radix_tree_node_ctor);
radix_tree_init_maxindex();
hotcpu_notifier(radix_tree_callback, 0);
}

五、基础操作函数

1.插入函数

int radix_tree_insert(struct radix_tree_root *root, unsigned long, void *item);

函数radix_tree_insert插入条目item到树root中,如果插入条目中内存分配错误,将返回错误-ENOMEM。该函数不能覆盖写正存在的条目。如果索引键值index已存在于树中,返回错误-EEXIST。插入操作成功返回0。

对于插入条目操作失败将引起严重问题的场合,下面的一对函数可避免插入操作失败:

int radix_tree_preload(gfp_t gfp_mask);
void radix_tree_preload_end(void);

函数radix_tree_preload尝试用给定的gfp_mask分配足够的内存,保证下一个插入操作不会失败。在调用插入操作函数之前调用此函数,分配的结构将存放在每CPU变量中。函数radix_tree_preload操作成功后,将关闭内核抢占。因此,在插入操作完成之后,用户应调用函数radix_tree_preload_end打开内核抢占。

2.删除函数

void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)

函数radix_tree_delete删除与索引键值index相关的条目,如果删除条目在树中,返回该条目的指针,否则返回NULL。

3.查询函数

/*在树中查找指定键值的条目,查找成功,返回该条目的指针,否则,返回NULL*/
void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index);
/*返回指向slot的指针,该slot含有指向查找到条目的指针*/
void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index);
/*多键值查找,max_items为需要查找的item个数,results表示查询结果。查询时键值索引从first_index开始*/
radix_tree_gang_lookup(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items);

4.标签操作

 /*将键值index对应的条目设置标签tag,返回值为设置标签的条目*/
void *radix_tree_tag_set(struct radix_tree_root *root, unsigned long index, unsigned int tag);
/*从键值index对应的条目清除标签tag,返回值为清除标签的条目*/
void *radix_tree_tag_clear(struct radix_tree_root *root, unsigned long index, unsigned int tag);
/*检查键值index对应的条目tag是否设置。tag参数为0或者1,表示Dirty位或者WB位
如果键值不存在,返回0,如果键值存在,但标签未设置,返回-1;如果键值存在,且标签已设置,返回1*/
int radix_tree_tag_get(struct radix_tree_root *root, unsigned long index, unsigned int tag);
/*从first_index起查询树root中标签值为tag的条目,在results中返回*/
unsigned int radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items, unsigned int tag);
/*如果树root中有任何条目使用tag标签,返回键值*/
int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);

Radix Tree总结相关推荐

  1. Redis radix tree源码解析

    Redis实现了不定长压缩前缀的radix tree,用在集群模式下存储slot对应的的所有key信息.本文将详述在Redis中如何实现radix tree. 核心数据结构 raxNode是radix ...

  2. redis radix tree的简单解释

    所有例子均出自源码. Radix tree压缩前缀树,是redis在5.0新加入的用来存储key的数据结构. 前缀树的节点结构如下. typedef struct raxNode {uint32_t ...

  3. 原始Radix Tree与路径压缩

    原始Radix Tree与路径压缩 Radix Tree简介 Radix tree 是一种前缀字典树,它的主要特点是树的高度不随数据库大小和节点数量改变,而是由 key 的长度决定.B树需要根据数据量 ...

  4. WORT: Write Optimal Radix Tree for Persistent Memory Storage Systems

    WORT: Write Optimal Radix Tree for Persistent Memory Storage Systems FAST17的一篇文章,介绍了内存索引中使用基数树保证数据一致 ...

  5. Linux: radix tree实现简析

    文章目录 1. 前言 2. 测试环境 3. 实现 3.1 概念 3.2 数据结构 3.3 对基数树的操作 3.3.1 初始化 3.3.2 插入 3.3.3 查找 3.3.4 删除 3.3.5 tag ...

  6. 【页高速缓存】radix tree 源码解析

    项目要在内核做和页高速缓存相类似缓存机制,在写内核代码之前必须先搞清楚页高速缓存源码是什么情况. 之前有一篇博客分析过了页高速缓存的基础,但是远远没有达到动手写代码的基础.这几天端午节假期集中精力,搞 ...

  7. 把数据转换为在内存中Tree(树形结构)。_Linux的中断处理机制 [二] - 数据结构(2)...

    Linux的中断处理机制 [一] - 数据结构(1) 上文提到,每个IRQ同时有"irq"和"hwirq"两个编号.这里"hwirq"是硬件 ...

  8. [原] 利用Radix树作为Key-Value 键值对的数据路由

    引言:总所周知,NoSQL,Memcached等作为Key-Value 存储的模型的数据路由都采用Hash表来达到目的.如何解决Hash冲突和Hash表大小的设计是一个很头疼的问题. 借助于Radix ...

  9. suffix tree

    文章出处:http://www.cnblogs.com/snowberg/archive/2011/10/21/2468588.html 3   What is a Suffix Tree Suffi ...

  10. 以太坊 Merkel-Patricia Tree(MPT)学习总结

    Merkel-Patricia Tree总体描述 ·Merkel-Patricia Tree中文名称梅克尔-帕特里夏树 ·MPT提供了一个基于密码学验证的底层数据结构,用来存储键值对(key-valu ...

最新文章

  1. 黄聪:解决Jquery在GET方式传递参数时gb2312中文编码乱码
  2. 从火热到理性,2019年AI芯片行业发展的怎么样了?【附PPT下载】
  3. 财务大数据比赛有python吗-Python 适合大数据量的处理吗?
  4. Common Lisp 初学者快速入门指导
  5. VTK:可视化之LabelPlacementMapper
  6. 解决XShell连接时无法root用户登录问题【Linux】
  7. Linux Shell脚本入门教程系列之(十二)Shell until循环
  8. 【BZOJ】1015 [JSOI2008]星球大战starwar(并查集+离线处理)
  9. html可以用坐标画svg图吗,HTML5如何使用SVG的方法示例
  10. pygame重新开始_Pygame(十八)音乐
  11. bundle adjustment原理(1)
  12. Vue_(组件)实例属性
  13. OSPF特殊区域NSSA以及T-NSSA配置详解
  14. 历史经验之QT在WIN32下编译环境配置步骤
  15. 不可多得的MBA相关书籍推荐
  16. 数据结构课程设计 神秘国度的爱情故事
  17. 健身行业大洗牌 Keep还会有未来吗?
  18. 使用react 写一个 仿淘宝 图片放大镜效果
  19. Python爬虫:调用百度翻译接口实现中英翻译功能
  20. 后ETC时代,年入近百亿元的千方科技如何玩转车路协同

热门文章

  1. P2184 贪婪大陆(线段树)
  2. 网页通用的测试用例(出处:: 51Testing-- lxp1119216)
  3. 唐山师范学院计算机论文,唐山师范学院
  4. CTF easycap Banmabanma
  5. 人文遥感 — 美丽兴化,千岛菜花
  6. FPGA设计之门控时钟
  7. png转bmp,png批量转成bmp
  8. coldfusion_ColdFusion 9有什么新功能?
  9. 【周赛266】leetcode2062.统计字符串中的的元音子字符串
  10. LVM 扩容---LVM扩展系统的根分区