映射也称之为关联数组,它是一组唯一键的集合,每个键与特定的值相关。一般支持至少三个操作:
-
Add(key,value)
-
Remove(key)
-
value=Lookup(key)
Linux提供了一个简单而有效的映射数据结构,它不是通用目的的映射,而是为特殊用例设计的:将UID(唯一标识号)映射到一个指针。除了提供三个主要的映射操作,还基于add操作的基础上提供了一个allocate操作。allocate操作不仅将添加一个UID/值对到映射中,还产生了一个UID。
idr数据结构用于映射用户空间的UID,例如inotify监视描述符到它们相关的内核数据结构中,如inotify_watch。
初始化idr
先静态定义或动态定义一个idr结构,然后调用idr_init():
void idr_init(struct idr *idp);
如:
struct idr id_huh; /* statically define idr structure */
idr_init(&id_huh);/* initialize provided idr structure */
分配一个新的UID
分两步进行,第一步告诉idr需要分配一个新的UID,使得它能在必要时重置后备树的大小,对应的函数为:
int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
第二步,请求新的UID,相应的函数为:
int idr_get_new(struct idr *idp, void *ptr, int *id);
例子如下:
intid; |
do{ |
if(!idr_pre_get(&idr_huh, GFP_KERNEL)) |
return-ENOSPC; |
ret= idr_get_new(&idr_huh, ptr, &id); |
}while (ret == -EAGAIN); |
int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int*id);
该函数的工作方式与idr_get_new()一样,不过它保证了新的UID大于或等于starting_id。它确保某个UID不被重用,并且保证了分析的UID在系统运行期间都是唯一的。
intid; do{ if(!idr_pre_get(&idr_huh, GFP_KERNEL)) return-ENOSPC; ret= idr_get_new_above(&idr_huh, ptr, next_id, &id); }while (ret == -EAGAIN); if(!ret) next_id = id + 1; |
查找一个UID
void*idr_find(struct idr *idp, int id);
structmy_struct *ptr = idr_find(&idr_huh, id); |
if(!ptr) |
return-EINVAL; /* error */ |
删除一个UID
void idr_remove(struct idr *idp, int id);
销毁一个udr
void idr_destroy(struct idr *idp);
如果想强制删除所有的UID,使用如下函数:
void idr_remove_all(struct idr *idp);
不过在调用idr_destroy()之前,要先在该idr上调用idr_remove_all(),确保所有的idr内存被释放。