1.IDR简述

idr在linux内核中指的就是整数ID管理机制,从本质上来说,这就是一种将整数ID号和特定指针关联在一起的机制。这个机制最早是在2003年2月加入内核的,当时是作为POSIX定时器的一个补丁。现在,在内核的很多地方都可以找到idr的身影。
idr机制适用在那些需要把某个整数和特定指针关联在一起的地方。举个例子,在I2C总线中,每个设备都有自己的地址,要想在总线上找到特定的设备,就必须要先发送该设备的地址。如果我们的PC是一个I2C总线上的主节点,那么要访问总线上的其他设备,首先要知道他们的ID号,同时要在pc的驱动程序中建立一个用于描述该设备的结构体。
此时,问题来了,我们怎么才能将这个设备的ID号和他的设备结构体联系起来呢?最简单的方法当然是通过数组进行索引,但如果ID号的范围很大(比如32位的ID号),则用数组索引显然不可能;第二种方法是用链表,但如果网络中实际存在的设备较多,则链表的查询效率会很低。遇到这种清况,我们就可以采用idr机制,该机制内部采用radix树实现,可以很方便地将整数和指针关联起来,并且具有很高的搜索效率。

2.idr源码分析

idr的源码位于linux/idr.h文件,本文使用linux5.5.4内核代码

2.1 idr结构体代码定义与初始化

struct idr {
    struct radix_tree_root    idr_rt;
    unsigned int        idr_base;
    unsigned int        idr_next;
};

其中,radix_tree_root定义为

define radix_tree_root        xarray

idr的初始化

// 静态初始化
#define IDR_INIT(name)    IDR_INIT_BASE(name, 0)

// 动态初始化
static inline void idr_init(struct idr *idr);

2.2 为idr分配内存

void idr_preload(gfp_t gfp_mask);

2.3 分配id号和指针关联

int idr_alloc(struct idr , void ptr, int start, int end, gfp_t);

2.4 通过id号搜索对应的指针

void idr_find(const struct idr , unsigned long id);

2.5 删除id

void idr_remove(struct idr , unsigned long id);

3.IDR使用