rbtree
红黑树(RBTree)是 Linux 内核中用于高效管理有序数据集合的一种自平衡树结构。以下是红黑树的基本概念及其在内核中的使用方法:
1. 定义红黑树
在使用红黑树之前,需要定义一个红黑树结构:
#include <linux/rbtree.h>
struct rb_root my_tree = RB_ROOT;
2. 定义节点结构
红黑树的每个节点通常包含数据和红黑树节点的结构:
struct my_node {
int key;
struct rb_node node;
};
3. 插入节点
使用 rb_add
函数插入新节点:
rb_add(&mng->task_node, &g_task_rbtree, task_rbtree_less);
static bool task_rbtree_less(struct rb_node *task_node, const struct rb_node *inserted_node)
{
const framework_task_mng *task_data = rb_entry(task_node, framework_task_mng, task_node);
const framework_task_mng *inserted_task_data = rb_entry(inserted_node, framework_task_mng, task_node);
return task_data->group_leader_pid < inserted_task_data->group_leader_pid;
}
4. 查找节点
使用 rb_find
函数查找节点:
node = rb_find((const void*)&group_leader_pid, &g_task_rbtree, task_rbtree_cmp);
static int32_t task_rbtree_cmp(const void *key, const struct rb_node *node)
{
const pid_t group_leader_pid = *(const pid_t*)key;
const framework_task_mng *task_data = rb_entry(node, framework_task_mng, task_node);
return group_leader_pid - task_data->group_leader_pid;
}
5. 删除节点
使用 rb_erase
删除节点:
struct rb_node *node_to_delete = /* 通过查找获得的节点 */;
rb_erase(node_to_delete, &my_tree);
kfree(container_of(node_to_delete, struct my_node, node));
6. 遍历红黑树
可以使用 rb_first
, rb_next
等函数进行遍历:
struct rb_node *node;
for (node = rb_first(&my_tree); node; node = rb_next(node)) {
struct my_node *data = container_of(node, struct my_node, node);
// 处理每个节点
}
// rb_first获取rbtree最左边的节点
若要遍历删除所有的节点,则使用:
for (node = rb_first(&my_tree); node != NULL; node = rb_first(node)) {
rb_erase
}
rb_entry
是 Linux 内核中用于方便地获取红黑树节点数据的宏。它通过红黑树节点的指针,返回包含该节点的结构体指针。
rb_entry
的定义如下:
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
- ptr: 指向红黑树节点的指针。
- type: 包含该节点的结构体类型。
- member: 该结构体中红黑树节点的成员名。
RB_ROOT
是 Linux 内核中用于定义红黑树的根节点的一个宏,用于创建一个初始的空红黑树。
mng->fw_pool_mng_rbtree = RB_ROOT;
7. RB_CLEAR_NODE
RB_CLEAR_NODE
是一个宏,用于清除红黑树(Red-Black Tree)节点的状态。RB_CLEAR_NODE
通常定义为将节点的颜色和父节点等信息重置为默认值,功能是将节点的状态清空,以便在重新使用或释放之前确保其状态的干净。
- 节点删除:在删除节点时,可能需要清除节点的状态,以便在后续操作(如重新插入)中使用。
- 节点初始化:在创建新节点时,通常会调用此宏来确保节点的状态是干净的。