Radix Tree总结
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总结相关推荐
- Redis radix tree源码解析
Redis实现了不定长压缩前缀的radix tree,用在集群模式下存储slot对应的的所有key信息.本文将详述在Redis中如何实现radix tree. 核心数据结构 raxNode是radix ...
- redis radix tree的简单解释
所有例子均出自源码. Radix tree压缩前缀树,是redis在5.0新加入的用来存储key的数据结构. 前缀树的节点结构如下. typedef struct raxNode {uint32_t ...
- 原始Radix Tree与路径压缩
原始Radix Tree与路径压缩 Radix Tree简介 Radix tree 是一种前缀字典树,它的主要特点是树的高度不随数据库大小和节点数量改变,而是由 key 的长度决定.B树需要根据数据量 ...
- WORT: Write Optimal Radix Tree for Persistent Memory Storage Systems
WORT: Write Optimal Radix Tree for Persistent Memory Storage Systems FAST17的一篇文章,介绍了内存索引中使用基数树保证数据一致 ...
- 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 ...
- 【页高速缓存】radix tree 源码解析
项目要在内核做和页高速缓存相类似缓存机制,在写内核代码之前必须先搞清楚页高速缓存源码是什么情况. 之前有一篇博客分析过了页高速缓存的基础,但是远远没有达到动手写代码的基础.这几天端午节假期集中精力,搞 ...
- 把数据转换为在内存中Tree(树形结构)。_Linux的中断处理机制 [二] - 数据结构(2)...
Linux的中断处理机制 [一] - 数据结构(1) 上文提到,每个IRQ同时有"irq"和"hwirq"两个编号.这里"hwirq"是硬件 ...
- [原] 利用Radix树作为Key-Value 键值对的数据路由
引言:总所周知,NoSQL,Memcached等作为Key-Value 存储的模型的数据路由都采用Hash表来达到目的.如何解决Hash冲突和Hash表大小的设计是一个很头疼的问题. 借助于Radix ...
- suffix tree
文章出处:http://www.cnblogs.com/snowberg/archive/2011/10/21/2468588.html 3 What is a Suffix Tree Suffi ...
- 以太坊 Merkel-Patricia Tree(MPT)学习总结
Merkel-Patricia Tree总体描述 ·Merkel-Patricia Tree中文名称梅克尔-帕特里夏树 ·MPT提供了一个基于密码学验证的底层数据结构,用来存储键值对(key-valu ...
最新文章
- 黄聪:解决Jquery在GET方式传递参数时gb2312中文编码乱码
- 从火热到理性,2019年AI芯片行业发展的怎么样了?【附PPT下载】
- 财务大数据比赛有python吗-Python 适合大数据量的处理吗?
- Common Lisp 初学者快速入门指导
- VTK:可视化之LabelPlacementMapper
- 解决XShell连接时无法root用户登录问题【Linux】
- Linux Shell脚本入门教程系列之(十二)Shell until循环
- 【BZOJ】1015 [JSOI2008]星球大战starwar(并查集+离线处理)
- html可以用坐标画svg图吗,HTML5如何使用SVG的方法示例
- pygame重新开始_Pygame(十八)音乐
- bundle adjustment原理(1)
- Vue_(组件)实例属性
- OSPF特殊区域NSSA以及T-NSSA配置详解
- 历史经验之QT在WIN32下编译环境配置步骤
- 不可多得的MBA相关书籍推荐
- 数据结构课程设计 神秘国度的爱情故事
- 健身行业大洗牌 Keep还会有未来吗?
- 使用react 写一个 仿淘宝 图片放大镜效果
- Python爬虫:调用百度翻译接口实现中英翻译功能
- 后ETC时代,年入近百亿元的千方科技如何玩转车路协同