山庄来客的专栏

Android, Linux Kernel Research Notes

内核数据结构之映射

映射也称之为关联数组,它是一组唯一键的集合,每个键与特定的值相关。一般支持至少三个操作:

  • 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内存被释放。



阅读更多
个人分类: Linux内核研究
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

内核数据结构之映射

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭