linux内核IDR机制详解【转】
这几天在看Linux内核的IPC命名空间时候看到关于IDR的一些管理性质的东西,刚开始看有些迷茫,深入看下去豁然开朗的感觉,把一些心得输出共勉。
我们来看一下什么是IDR?IDR的作用是什么呢?
先来看下IDR的作用:IDR主要实现ID与数据结构的绑定。刚开始看的时候感觉到有点懵,什么叫“ID与数据结构的绑定”?举一个例子大家就会明白了:在IPC通信的时候先要动态获取一个key值或者使用现有的key值进行通信,那么系统怎么知道这个key值是否使用了呢?这个就需要IDR来进行判断了。以上就是IDR的一些浅显的概念,IDR本质上就是通过对于ID一些有效的管理进而管理和这些ID有关的数据结构----不限于IPC通信的key值。
IDR怎么对于数据ID管理呢?传统上我们对于未使用的ID进行管理的时候可以使用位图进行管理,也可以使用数组进行管理,也可以使用链表进行ID管理,三个个各有优缺点:
- 使用位图进行管理的时候优点是使用空间少,但是对于位图对应的数据结构支持不太友好。
- 使用数组进行管理的时候寻址快速,但是只能管理比较少量的ID数目。
- 使用链表进行管理的时候虽然可以支持大量的数据ID,但是通过链表的指针寻址比较慢。
所以引入了以上三者的优点进行IDR管理。
IDR管理的核心
IDR把每一个ID分级数据进行管理,每一级维护着ID的5位数据,这样就可以把IDR分为7级进行管理(5*7=35,维护的数据大于32位),如下所示:
31 30 | 29 28 27 26 25 | 24 23 22 21 20 | 19 18 17 16 15 | 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
例如数据ID为0B 10 11111 10011 00111 11001 100001 00001,寻址如下:
1. 第一级寻址 ary1[0b10]得到第二级地址ary2[]2. ary3 = ary2[0b11111]3. ary4 = ary3[ob10011]4. ary5 = ary4[0b00111]5. ary6 = ary5[0b11001]6. ary7 = ary6[0b100001]7. ary8 = ary7[0b00001]
ary8即为要寻址到的ID对应的IDR指针。
如下图:
上图中每一个分级中的IDR数组中的值不为空代表相应位有效的ID位,但是使用数组下标标示有效的ID位还是有点慢----需要通过数组下标以及数组内容判断有效的ID位,所以对于每一个IDR引入了有效的ID位图来表示,每一个位图为32位刚好给出了相应的有效的ID位。方便查找。
上图中只是使用了IDR的32个数组表示,并没有给出IDR的位图以及层数标志,下面给出相应的数据结构:
IDR 数据结构:
struct idr_layer {//位图,ary数组结构哪个有效unsigned long bitmap; /* A zero bit means "space here" *///IDR数组struct idr_layer __rcu *ary[1<<IDR_BITS];标示int count; /* When zero, we can release it *///层数,代表所在的ID位int layer; /* distance from leaf */struct rcu_head rcu_head;
};struct idr {//IDR层数头,实际上就是32叉树struct idr_layer __rcu *top;//尚未使用的IDRstruct idr_layer *id_free;//层数int layers; /* only valid without concurrent changes *///id_free未用的个数;int id_free_cnt;spinlock_t lock;
};
下面讨论一下IDR的初始化以及增删改查ID问题:
- IDR的初始化
- IDR的增加
- IDR的查找
IDR的初始化:
IDR的初始化相对来说比较简单,使用IDR_INIT可以初始化一个IDR,原型如下:
#define IDR_INIT(name) \
{ \.top = NULL, \.id_free = NULL, \.layers = 0, \.id_free_cnt = 0, \.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
}
可以看到IDR只是把各个数据值为零,原子锁初始化下。
IDR的增加:
IDR增加比较复杂,在C中编程大部分情况可以分为如下两点讨论:
1.idr.top为NULL的情况;2.idr.top不为NULL的情况;以上考虑问题也是可以的,但是没有考虑到如下问题:每一个idr_layer结构体有一个layer标示,我们每每增加一层,就要遍历整个idr的32叉树。无形中增加了系统负担。
idr设计者在考虑问题时候恰恰相反,没增加一个idr_layer层,就把要增加的idr_layer->ary[0]指向旧的idr_layer树的根,把要增加idr_layer->layer赋予旧的根部的idr_layer->layer + 1值,这样就不会考虑到idr->top为NULL的情况了。ps:只需要判断在增加第一个idr_layer时候判断一下,并且把idr_layer->layer值赋为0.
IDR的查找:
在查找IDR时侯会先查找IDR根节点,然后根据ID位所在的层的值遍历IDR树,如果查找到某一段树为NULL,则会返回NULL。
以下是IDR查找的过程:
void *idr_find(struct idr *idp, int id)
{ int n;struct idr_layer *p; //获取根IDRp = rcu_dereference_raw(idp->top);if (!p)return NULL;/**根据IDR的层数获取要遍历的个数;**/n = (p->layer+1) * IDR_BITS;/* 去除我们不需要查找的位数. */id &= MAX_ID_MASK;/***如果ID值大于n, 1<<n为根据层数换算过来的ID的最大值**/if (id >= (1 << n))return NULL;BUG_ON(n == 0);/***遍历顺序:28---->0,每次减少5位,可以遍历完全IDR的32叉树***/while (n > 0 && p) {n -= IDR_BITS;BUG_ON(n != p->layer*IDR_BITS);p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]);}return((void *)p);
}
转载于:https://www.cnblogs.com/linhaostudy/p/10535455.html
linux内核IDR机制详解【转】相关推荐
- linux内核IDR机制详解(一)
这几天在看Linux内核的IPC命名空间时候看到关于IDR的一些管理性质的东西,刚开始看有些迷茫,深入看下去豁然开朗的感觉,把一些心得输出共勉. 我们来看一下什么是IDR?IDR的做作用是什么呢? 先 ...
- linux内核rcu,linux内核rcu机制详解
RCU(Read-Copy Update)是数据同步的一种方式,在当前的Linux内核中发挥着重要的作用.RCU主要针对的数据对象是链表,目的是提高遍历读取数据的效率,为了达到目的使用RCU机制读取数 ...
- linux内核 RCU机制详解
简介 RCU(Read-Copy Update)是数据同步的一种方式,在当前的Linux内核中发挥着重要的作用.RCU主要针对的数据对象是链表,目的是提高遍历读取数据的效率,为了达到目的使用RCU机制 ...
- Linux内核Thermal框架详解十四、Thermal Governor(4)
本文部分内容参考 万字长文 | Thermal框架源码剖析, Linux Thermal机制源码分析之框架概述_不捡风筝的玖伍贰柒的博客-CSDN博客, "热散由心静,凉生为室空" ...
- Linux内核Thermal框架详解十三、Thermal Governor(3)
接前一篇文章Linux内核Thermal框架详解十二.Thermal Governor(2) 二.具体温控策略 上一篇文章介绍并详细分析了bang_bang governor的源码.本文介绍第2种温控 ...
- Linux内核Thermal框架详解十二、Thermal Governor(2)
本文部分内容参考 万字长文 | Thermal框架源码剖析, Linux Thermal机制源码分析之框架概述_不捡风筝的玖伍贰柒的博客-CSDN博客, "热散由心静,凉生为室空" ...
- 【正点原子Linux连载】第三十五章 Linux内核顶层Makefile详解 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- linux内核I2C子系统详解
1.I2C通信协议 参考博客:<I2C通信协议详解和通信流程分析>:https://csdnimg.cn/release/blogv2/dist/pc/themesSkin/skin3-t ...
- cgroup使用举例和linux内核源码详解
cgroup的原理其实并不复杂,用法也比较简单.但是涉及的内核数据结构真的复杂,错综复杂的数据结构感觉才是cgroup真正的难点.本文结合个人学习cgroup源码的心得,尽可能以举例的形式,总结cgr ...
最新文章
- git 换行问题_后端必备的 Git 分支开发规范指南
- xcode7.2 真机测试
- 【特征工程】17种将离散特征转化为数字特征的方法
- 逆向工程核心原理学习笔记(十四):栈帧1
- IIS8托管WCF服务
- android实例化一个活动,Android活动 - 无法实例化活动组件信息
- js 动态生成HTML,并加载事件遇到的问题
- jQuery-EasyUI
- 清华大学操作系统OS学习(十四)——文件系统和文件描述符
- 正则表达式匹配EXCEL地址字符串
- java -jar bat_java jar包和bat批处理命令
- 内网渗透思路学习——靶场实战——暗月项目七
- NLP学习(七)使用stanford实现句法分析-Python3实现
- mysql relay log_mysql binlog和relay log日志如何清除
- VMware Workstation中安装系统和VMware tools
- 翼支付个人自定义收款接口
- android仿小米日历,实现一个仿小米日历控件
- CAS配置数据库,实现数据库用户认证
- 利用定时/计数器T1产生定时时钟,由P1口控制8个发光二极管,使8个提示灯依次一个一个闪动,闪动频率为10次每秒(8个灯亮一遍为一个周期),循环
- chrome清除https状态
热门文章
- 统一并发 III——跨基准测试
- 木兰编程语言重现——支持列表操作,演示编辑器高亮
- 带有进度报告的Angular 9/8多文件上传服务
- 甲骨文通知用户需付费取得 Java 8 更新
- android 应用置顶到最前端_uniApp / 小程序实现一个view滚动到一定高度置顶显示
- mysql 计算非重复_MySQL Query:在一个非常庞大的表中计算重复值
- 面包板如何接线电源 图解_互感器、电能表接线和原理讲解
- 微信分享踩坑:config:invalid signature错误的解决方法
- 橱柜高度与身高对照表_厨房台面高度是多少 厨房台面如何选购
- 解读mysql日志_全方位解读 MySQL 日志实现内幕(四)