基数树radix_tree_root

linux 内存管理通过radix树跟踪绑定到地址映射上的核心页,

该radix树允许内存管理代码快速查找标识为dirty或writeback的页。Linux radix树的API函数在lib/radix-tree.c中实现。

一:主要的数据结构
struct radix_tree_root {
	unsigned int		height;//树总高
	gfp_t			gfp_mask;//内存的分配方式
	struct radix_tree_node	__rcu *rnode;
};

struct radix_tree_node {
	unsigned int	height;		/* Height from the bottom */
	unsigned int	count;
	struct rcu_head	rcu_head;
	void __rcu	*slots[RADIX_TREE_MAP_SIZE];//存放指针的数组
	unsigned long	tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
};
二:初始化
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);
}
kmem_cache_create 从slab分配数据结构,主要看 radix_tree_init_maxindex函数

static __init unsigned long __maxindex(unsigned int height)
{
	unsigned int width = height * RADIX_TREE_MAP_SHIFT;
	int shift = RADIX_TREE_INDEX_BITS - width;

	if (shift < 0)
		return ~0UL;
	if (shift >= BITS_PER_LONG)//16
		return 0UL;
	return ~0UL >> shift;
}

static __init void radix_tree_init_maxindex(void)
{
	unsigned int i;
	for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++)
		height_to_maxindex[i] = __maxindex(i);
}
分析函数得:
height_to_maxindex[0] = 0  height_to_maxindex[1] = 16  height_to_maxindex[2] = 256  ...... 
二:初始化结构体图

四,主要的函数操作

    插入函数

nt radix_tree_insert(struct radix_tree_root *root,
			unsigned long index, void *item)
{

	if (index > radix_tree_maxindex(root->height)) {//发现需要插入的index大于目前树的叶子个数
		error = radix_tree_extend(root, index);//扩展树
		if (error)
			return error;
	}

	shift = (height-1) * RADIX_TREE_MAP_SHIFT;

	offset = 0;			/* uninitialised var warning */
	while (height > 0) {
		if (slot == NULL) {
			/* Have to add a child node.  */
			if (!(slot = radix_tree_node_alloc(root)))
				return -ENOMEM;
			slot->height = height;
			if (node) {
				rcu_assign_pointer(node->slots[offset], slot);
				node->count++;
			} else
				rcu_assign_pointer(root->rnode, ptr_to_indirect(slot));
		}

		/* Go a level down */
		offset = (index >> shift) & RADIX_TREE_MAP_MASK;
		node = slot;
		slot = node->slots[offset];
		shift -= RADIX_TREE_MAP_SHIFT;
		height--;
	}
	return 0;
}
static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
{....
	do {
		unsigned int newheight;
		if (!(node = radix_tree_node_alloc(root)))
			return -ENOMEM;

		/* Increase the height.  */
		node->slots[0] = indirect_to_ptr(root->rnode);

		/* Propagate the aggregated tag info into the new root */
		for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
			if (root_tag_get(root, tag))
				tag_set(node, tag, 0);
		}

		newheight = root->height+1;
		node->height = newheight;
		node->count = 1;
		node = ptr_to_indirect(node);
		rcu_assign_pointer(root->rnode, node);
		root->height = newheight;
	} while (height > root->height);
}

扩展树后图列如下:


插入具体的index,与数据,假如index = 37,二进制位100101

即10,0101, 10=2,0101=5 即得到图下结果


查找函数

static void *radix_tree_lookup_element(struct radix_tree_root *root,
				unsigned long index, int is_slot)
{

....
	do {
		slot = (struct radix_tree_node **)
			(node->slots + ((index>>shift) & RADIX_TREE_MAP_MASK));
		node = rcu_dereference_raw(*slot);
		if (node == NULL)
			return NULL;

		shift -= RADIX_TREE_MAP_SHIFT;
		height--;
	} while (height > 0);

	return is_slot ? (void *)slot : indirect_to_ptr(node);
}
按照index,
(index>>shift 左移,来查找,找不到返回空,如果找到返回存储地址

扫描二维码关注公众号,回复: 996755 查看本文章

猜你喜欢

转载自blog.csdn.net/flyxiao28/article/details/80368353