我有一个毛病就是不爱读源代码, 总是喜欢从宏观上看逻辑架构, 对于一些比较通用的代码,网上的分析很多,这个方法学起来的确比较快,毕竟源码,尤其是代码量比较多的源码,读起来是很费力的.但是现在越来越多的遇到一些code,网上查也查不太到,我就不得不自己去读源码了.
也好,读源码的能力还是要锻炼的.
Read the Fucking Source Code!
水平有限,不保证内容完全正确,如有错误,烦请指正。
简介: IDR机制在Linux内核中指的是整数ID管理机制。实质上来讲,这就是一种将一个整数ID号和一个指针关联在一起的机制。
IDA是用IDR来实现的ID分配机制,与IDR的区别是IDA仅仅分配与管理ID,并不将ID与指针相关联.
参考源码版本: linux 3.10
先看IDR:
IDR采用树结构+bitmap来管理ID与指针的分配, 不过不是简单的2叉树,而是256叉树!
每个树节点有256个分支(树枝), 每个分支以指针指向下一层的树节点, 最顶层的节点叫做树叶, 树叶作为特殊的节点其分支不再指向其他节点, 而是直接包含我们要关联的指针, 因此每个树叶拥有256个指针.
那么与指针关联的ID如何记录呢?
每个树节点包含一个256位的bitmap结构, 每位bit代表一个分支, 当这个分支下包含的所有树叶都被分配满指针时,此位置1. 对于最终存放指针的树叶,其也有一个256位的bitmap, 其中每一位表示对应的指针。 置1表示对应的指针被分配,置0表示空闲。 当一个指针被分配时, 这个指针对应的ID由该指针对应的bit在这个树叶的bitmap的位置, 以及该指针所在的树叶在整个树的位置来记录.
为什么不用2叉树? 很简单, 对于大量的ID整型数, 2叉树的叶子太少,需要大量增加树的层次.不便于计算.
再看IDA:
/**
* DOC: IDA description
* IDA - IDR based ID allocator
*
* This is id allocator without id -> pointer translation. Memory
* usage is much lower than full blown idr because each id only
* occupies a bit. ida uses a custom leaf node which contains
* IDA_BITMAP_BITS slots.
*
* 2007-04-25 written by Tejun Heo <htejun@gmail.com>
*/
IDA只不过是对IDR的一个封装,IDA不需要记录指针,仅仅是分配与管理ID. 因此IDA的树叶的每个分支指向一个Ida bitmap, 这个bitmap中的每一个bit负责记录ID, 置1表示已分配, 置0表示未分配. ID号由对应的bit在IDA bitmap中的位置以及IDA bitmap在整个树中的位置表示.
先看IDA及IDR的定义, 定义在idr.h头文件中(include/linux/idr,h)
IDR定义如下:
#define IDR_BITS 8
#define IDR_SIZE (1 << IDR_BITS)
#define IDR_MASK ((1 << IDR_BITS)-1)
struct idr_layer {
int prefix; /* the ID prefix of this idr_layer */
DECLARE_BITMAP(bitmap, IDR_SIZE); /* A zero bit means "space here" */
struct idr_layer __rcu *ary[1<<IDR_BITS];
int count; /* When zero, we can release it */
int layer; /* distance from leaf */
struct rcu_head rcu_head;
};
struct idr {
struct idr_layer __rcu *hint; /* the last layer allocated from */
struct idr_layer __rcu *top;
struct idr_layer *id_free;
int layers; /* only valid w/o concurrent changes */
int id_free_cnt;
int cur; /* current pos for cyclic allocation */
spinlock_t lock;
};
struct idr_layer 表示一个树节点,layer成员表示该节点位于树的第几层,树叶为第0层,越往树根layer越大。prefix是表示layer的一个ID,同一层的所有节点共享同一个prefix,For layer 0, the prefix mask is all bits except for the lower IDR_BITS (0xFFFFFF00),For layer 1, the prefix mask is all bits except for the lower 2 * IDR_BITS (0xFFFF0000), and so on...