Linux内核源码分析-基树处理- radix_tree

Linux内核源码分析-基树处理- radix_tree

本文主要参考《深入理解Linux内核》,结合2.6.11版的内核代码,分析内核文件子系统中的radix_tree处理函数。
注意:
1、 不描述内核同步、错误处理、参数合法性验证相关的内容
2、 源码摘自Linux内核2.6.11 stable版,获取命令:
git clone
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd ./linux-stable/
git checkout linux-2.6.11.y
3、 阅读本文请结合《深入理解Linux内核》第三版相关章节
4、 本文会不定时更新

函数调用结构

这里写图片描述

公共函数

1、radix_tree_init
源码:
在init/main.c:start_kernel函数中调用该函数

void __init radix_tree_init(void)
{
    radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
            sizeof(struct radix_tree_node), 0,
            SLAB_PANIC, radix_tree_node_ctor, NULL);
    radix_tree_init_maxindex();
    hotcpu_notifier(radix_tree_callback, 0);
}

处理流出:
1、 调用函数kmem_cache_create分配类型为radix_tree_node、名称为radix_tree_node的slab高速缓存,存入全局变量radix_tree_node_cachep中
2、 调用函数radix_tree_init_maxindex初始化书中各层的最大索引数组height_to_maxindex(1-6层)
3、 调用函数hotcpu_notifier,设置热插拔cpu时的回调函数
2、radix_tree_insert
源码:

/**
 *  radix_tree_insert    -    insert into a radix tree
 *  @root:      radix tree root
 *  @index:     index key
 *  @item:      item to insert
 *
 *  Insert an item into the radix tree at position @index.
 */
int radix_tree_insert(struct radix_tree_root *root,
            unsigned long index, void *item)
{
    struct radix_tree_node *node = NULL, *tmp, **slot;
    unsigned int height, shift;
    int offset;
    int error;

    /* Make sure the tree is high enough.  */
    if ((!index && !root->rnode) ||
            index > radix_tree_maxindex(root->height)) {
        error = radix_tree_extend(root, index);
        if (error)
            return error;
    }

    slot = &root->rnode;
    height = root->height;
    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 (!(tmp = radix_tree_node_alloc(root)))
                return -ENOMEM;
            *slot = tmp;
            if (node)
                node->count++;
        }

        /* Go a level down */
        offset = (index >> shift) & RADIX_TREE_MAP_MASK;
        node = *slot;
        slot = (struct radix_tree_node **)(node->slots + offset);
        shift -= RADIX_TREE_MAP_SHIFT;
        height--;
    }

    if (*slot != NULL)
        return -EEXIST;
    if (node) {
        node->count++;
        BUG_ON(tag_get(node, 0, offset));
        BUG_ON(tag_get(node, 1, offset));
    }

    *slot = item;
    return 0;
}

处理流程:
1、 调用函数radix_tree_extend扩展树的层数以满足index
2、 循环初始化各层的radix_tree_node对象
3、 初始化最终的页的指针
3、radix_tree_delete
源码:

/**
 *  radix_tree_delete    -    delete an item from a radix tree
 *  @root:      radix tree root
 *  @index:     index key
 *
 *  Remove the item at @index from the radix tree rooted at @root.
 *
 *  Returns the address of the deleted item, or NULL if it was not present.
 */
void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
{
    struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
    struct radix_tree_path *orig_pathp;
    unsigned int height, shift;
    void *ret = NULL;
    char tags[RADIX_TREE_TAGS];
    int nr_cleared_tags;

    height = root->height;
    if (index > radix_tree_maxindex(height))
        goto out;

    shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
    pathp->node = NULL;
    pathp->slot = &root->rnode;

    while (height > 0) {
        int offset;

        if (*pathp->slot == NULL)
            goto out;

        offset = (index >> shift) & RADIX_TREE_MAP_MASK;
        pathp[1].offset = offset;
        pathp[1].node = *pathp[0].slot;
        pathp[1].slot = (struct radix_tree_node **)
                (pathp[1].node->slots + offset);
        pathp++;
        shift -= RADIX_TREE_MAP_SHIFT;
        height--;
    }

    ret = *pathp[0].slot;
    if (ret == NULL)
        goto out;

    orig_pathp = pathp;

    /*
     * Clear all tags associated with the just-deleted item
     */
    memset(tags, 0, sizeof(tags));
    do {
        int tag;

        nr_cleared_tags = RADIX_TREE_TAGS;
        for (tag = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值