缥缈峰一座01号

梁二伯的窝

  DonewsBlog  |  Donews首页  |  Donews社区  |  Donews邮箱  |  我的首页  |  联系作者  |  聚合   |  登录
  86篇文章 :: 0篇收藏:: 27篇评论:: 0个Trackbacks

公告

Equality && Free

文章

收藏

相册

存档


正在读取评论……


radix树是2.6内核中的增加的重要结构,是各种页面操作文件操作的重要结构之一。

头节点:
struct radix_tree_root {
 unsigned int  height; //树高度
 gfp_t   gfp_mask;
 struct radix_tree_node *rnode;
};

节点:
struct radix_tree_node {
 unsigned int count;  //slots数组中非NULL项个数
 void  *slots[RADIX_TREE_MAP_SIZE]; //存储radix_tree_node的指针(非叶节点)或page结构指针(叶节点)
 unsigned long tags[RADIX_TREE_TAGS][RADIX_TREE_TAG_LONGS];  //用以存储上面slots中指针内容指向结构的flag
              //前面为每个项的标志位个数,后面位项的个数 
};

几个常见操作:

//===================================================================================
//初始化:在slab中分配一个cache存放radix_tree_node


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();  //初始化height_to_maxindex[]数组
 hotcpu_notifier(radix_tree_callback, 0);
}

//计算每个height中最大index,初始化height_to_maxindex[]数组
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);
}

static __init unsigned long __maxindex(unsigned int height)
{
 unsigned int tmp = height * RADIX_TREE_MAP_SHIFT;
 //不明白为什么不用 (~0UL >> (RADIX_TREE_INDEX_BITS - tmp ))
 unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1;

 if (tmp >= RADIX_TREE_INDEX_BITS)
  index = ~0UL;  //height为6时候最大为0xFFFFFFFF
 return index;
}

//===================================================================================

/**
 * radix_tree_insert    -    insert into a radix tree
 * @root:  radix tree root
 * @index:  index key (倘若是page结构指针就是其线性地址)
 * @item:  item to insert(可以是page的指针或node的指针)
 *
 * 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, *slot;
 unsigned int height, shift;
 int offset;
 int error;

 /* 倘若index与根结点指向节点都为空,或index超过树的最大容量  */
 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; //计算偏移量 RADIX_TREE_MAP_SHIFT为6

 offset = 0;   /* uninitialised var warning */
 do {
  if (slot == NULL) {
   /* 加入一个子节点  */
   if (!(slot = radix_tree_node_alloc(root)))
    return -ENOMEM;
   if (node) {
    node->slots[offset] = slot;
    node->count++;
   } else
    root->rnode = slot; //为根节点建立一个子节点
  }

  /* Go a level down */
  offset = (index >> shift) & RADIX_TREE_MAP_MASK;//计算index
  node = slot;
  slot = node->slots[offset];
  shift -= RADIX_TREE_MAP_SHIFT;
  height--;
 } while (height > 0);

 if (slot != NULL)
  return -EEXIST;

 BUG_ON(!node);
 node->count++;
 node->slots[offset] = item;
 BUG_ON(tag_get(node, 0, offset));
 BUG_ON(tag_get(node, 1, offset));

 return 0;
}

//=======================================================================================
很简单的取得slots数组中的对应index的指针的指针
static inline void **__lookup_slot(struct radix_tree_root *root,
       unsigned long index)
{
 unsigned int height, shift;
 struct radix_tree_node **slot;

 height = root->height;
 if (index > radix_tree_maxindex(height))
  return NULL;

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

 while (height > 0) {
  if (*slot == NULL)
   return NULL;

  slot = (struct radix_tree_node **)
   ((*slot)->slots +
    ((index >> shift) & RADIX_TREE_MAP_MASK));
  shift -= RADIX_TREE_MAP_SHIFT;
  height--;
 }

 return (void **)slot;
}
//=======================================================================================
//顾名思义通过index取得存储指针的slot
void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index)
{
 return __lookup_slot(root, index);
}
EXPORT_SYMBOL(radix_tree_lookup_slot);

//顾名思义通过index取得slot中的指针
void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
{
 void **slot;

 slot = __lookup_slot(root, index);
 return slot != NULL ? *slot : NULL;
}
//=======================================================================================
/**
 * 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;
 struct radix_tree_node *slot;
 unsigned int height, shift;
 void *ret = NULL;
 char tags[RADIX_TREE_TAGS];
 int nr_cleared_tags;
 int tag;
 int offset;

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

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

 for ( ; height > 0; height--) {
  if (slot == NULL)
   goto out;

  pathp++;
  offset = (index >> shift) & RADIX_TREE_MAP_MASK;
  pathp->offset = offset;
  pathp->node = slot;
  slot = slot->slots[offset];
  shift -= RADIX_TREE_MAP_SHIFT;
 }

 ret = slot;
 if (ret == NULL)
  goto out;

 orig_pathp = pathp;

 /*
  * Clear all tags associated with the just-deleted item
  */
 nr_cleared_tags = 0;
 for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
  tags[tag] = 1;
  if (tag_get(pathp->node, tag, pathp->offset)) {
   tag_clear(pathp->node, tag, pathp->offset);
   if (!any_tag_set(pathp->node, tag)) {
    tags[tag] = 0;
    nr_cleared_tags++;
   }
  }
 }

 for (pathp--; nr_cleared_tags && pathp->node; pathp--) {
  for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
   if (tags[tag])
    continue;

   tag_clear(pathp->node, tag, pathp->offset);
   if (any_tag_set(pathp->node, tag)) {
    tags[tag] = 1;
    nr_cleared_tags--;
   }
  }
 }

 /* Now free the nodes we do not need anymore */
 for (pathp = orig_pathp; pathp->node; pathp--) {
  pathp->node->slots[pathp->offset] = NULL;
  pathp->node->count--;

  if (pathp->node->count) {
   if (pathp->node == root->rnode)
    radix_tree_shrink(root);
   goto out;
  }

  /* Node with zero slots in use so free it */
  radix_tree_node_free(pathp->node);
 }
 root->rnode = NULL;
 root->height = 0;
out:
 return ret;
}



Trackback: http://tb.donews.net/TrackBack.aspx?PostId=1008752


[点击此处收藏本文]  发表于2006年08月21日 9:10 AM




正在读取评论……

发表评论

大名:
网址:
验证码
评论