浅析linux内核中的idr机制
作者 佚名技术
来源 Linux系统
浏览
发布时间 2012-05-13
尚观科技原创文章
浅析linux内核中的idr机制
尚观讲师原创文章 idr在linux内核中指的就是整数ID管理机制,从本质上来说,这就是一种将整数ID号和特定指针关联在一起的机制.这个机制最早是在2003年2月加入内核的,当时是作为POSIX定时器的一个补丁.现在,在内核的很多地方都可以找到idr的身影. idr机制适用在那些需要把某个整数和特定指针关联在一起的地方.举个例子,在I2C总线中,每个设备都有自己的地址,要想在总线上找到特定的设备,就要先发送该设备的地址.如果我们的PC是一个I2C总线上的主节点,那么要访问总线上的其他设备,要知道他们的ID号,同时要在pc的驱动程序中建立一个用于描述该设备的结构体. 此时,问题来了,我们怎么才能将这个设备的ID号和他的设备结构体联系起来呢?最简单的方法当然是通过数组进行索引,但如果ID号的范围很大(比如32位的ID号),则用数组索引显然不可能;第二种方法是用链表,但如果网络中实际存在的设备较多,则链表的查询效率会很低.遇到这种清况,我们就可以采用idr机制,该机制内部采用radix树实现,可以很方便地将整数和指针关联起来,并且具有很高的搜索效率. (1)获得idr 要在代码中使用idr,要包括<linux/idr.h>.接下来,我们要在代码中分配idr结构体,并初始化: void idr_init(struct idr *idp); 其中idr定义如下: struct idr { struct idr_layer *top; struct idr_layer *id_free; int layers; int id_free_cnt; spinlock_t lock; }; /* idr是idr机制的核心结构体 */ (2)为idr分配内存 int idr_pre_get(struct idr *idp, unsigned int gfp_mask); 每次通过idr获得ID号之前,需要先分配内存. 返回0表示错误,非零值代表正常 (3)分配ID号并将ID号和指针关联 int idr_get_new(struct idr *idp, void *ptr, int *id); int idr_get_new_above(struct idr *idp, void *ptr, int start_id, int *id); idp: 之前通过idr_init初始化的idr指针 id: 由内核自动分配的ID号 ptr: 和ID号相关联的指针 start_id: 起始ID号.内核在分配ID号时,会从start_id开始.如果为I2C节点分配ID号,可以将设备地址作为start_id 函数调用正常返回0,如果没有ID可以分配,则返回-ENOSPC 在实际中,上述函数常常采用如下方式使用: again: if (idr_pre_get(&my_idr, GFP_KERNEL) == 0) { /* No memory, give up entirely */ } spin_lock(&my_lock); result = idr_get_new(&my_idr, &target, &id); if (result == -EAGAIN) { sigh(); spin_unlock(&my_lock); goto again; } (4)通过ID号搜索对应的指针 void *idr_find(struct idr *idp, int id); 返回值是和给定id相关联的指针,如果没有,则返回NULL (5)删除ID 要删除一个ID,使用: void idr_remove(struct idr *idp, int id); 通过上面这些方法,内核代码可以为子设备,inode生成对应的ID号.这些函数都定义在<linux-2.6.xx/lib/idr.c>中 下面,我们通过分析I2C协议的核心代码,来看一看idr机制的实际应用: <linux-2.6.23/drivers/i2c/i2c-core.c> ... <linux/idr.h> /* idr头文件 */ ... static DEFINE_IDR(i2c_adapter_idr); /* 声明idr */ ... /* 采用动态总线号声明并注册一个i2c适配器(adapter),可睡眠 针对总线号可动态指定的设备,如基于USB的i2c设备或pci卡 */ int i2c_add_adapter(struct i2c_adapter *adapter) { int id, res = 0; retry: if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) return -ENOMEM; mutex_lock(&core_lists); /* __i2c_first_dynamic_bus_num是当前系 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |
你可能对下面的文章感兴趣
上一篇: bind 完成正确安装下一篇: ln 命令
关于浅析linux内核中的idr机制的所有评论