引言
radix-tree在linux文件系统和句柄表使用的一种高效数据结构。它通过类似B+树的原理建立ID与数据指针的映射,并且通过rcu机制提供数据安全性和高效性。
1 使用介绍
1.1 定义变量
struct radix_tree_root g_rdtree_root;
注:radix_tree_root也可以嵌套到结构体中
1.2 初始化
INIT_RADIX_TREE(&g_rdtree_root, GFP_KERNEL);
1.3 预分配
//预分配空间
int err = radix_tree_preload(GFP_KERNEL); //成功后关闭内核抢占
if (err) {
goto fail;
}
# 略略略... ...
radix_tree_preload_end(); //打开内核抢占
1.4 插入节点
int err = radix_tree_insert(&g_rdtree_root, index, xxx_ptr);
1.5 删除节点
struct xxx_st* xxx_ptr = radix_tree_delete(&g_rdtree_root, index);
1.6 替换节点
void __rcu **slot = radix_tree_lookup_slot(&g_rdtree_root, index);
if (slot) {
radix_tree_replace_slot(&g_rdtree_root, slot, xxx_new_ptr);
}
1.7 查询遍历
//查询单个节点
struct xxx_st* xxx_ptr = radix_tree_lookup(&g_rdtree_root, index);
//查询连续节点
struct xxx_st* xxx_ptrs[16];
count = radix_tree_gang_lookup(&g_rdtree_root, (void **)xxx_ptrs, index, 16);
//从begin_index往后遍历
struct radix_tree_iter iter;
radix_tree_for_each_slot(slot, &g_rdtree_root, &iter, begin_index) {
# 略略略... ...
}
1.8 安全访问
- 安全读
rcu_read_lock();
void __rcu **slot = radix_tree_lookup_slot(&g_rdtree_root, index);
if (slot) {
struct xxx_st* xxx_tmp = rcu_dereference(*slot);
# 略略略... ...
}
rcu_read_unlock();
- 安全写
spin_lock(&g_rdtree_lock);
void __rcu **slot = radix_tree_lookup_slot(&g_rdtree_root, index);
struct xxx_st* xxx_old_ptr = slot ? radix_tree_deref_slot_protected(slot, &g_rdtree_lock) : NULL;
if (slot) {
radix_tree_replace_slot(&g_rdtree_root, slot, xxx_new_ptr);
} else {
radix_tree_insert(&g_rdtree_root, index, xxx_new_ptr);
}
spin_unlock(&g_rdtree_lock);
if (xxx_old_ptr) {
synchronize_rcu();
kfree(xxx_old_ptr);
}
1.9 标签操作
//设置tag
struct xxx_st* xxx_ptr = radix_tree_tag_set(&g_rdtree_root, index, tag);
//清除tag
struct xxx_st* xxx_ptr = radix_tree_tag_clear(&g_rdtree_root, index, tag);
//判断index是否标记, 存在返回1、否则返回0
int tagged = radix_tree_tag_get(&g_rdtree_root, index, tag);
//判断是否存在tag的index, 存在返回非0、否则返回0
int tagged = radix_tree_tagged(&g_rdtree_root, tag);
//查询tag
struct xxx_st* xxx_ptrs[16];
int size = radix_tree_gang_lookup_tag(&g_rdtree_root, (void **)xxx_ptrs, first_index, 16, tag);
注:tag必须小于RADIX_TREE_MAX_TAGS