浅析linux内核中的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;
};
int idr_pre_get(struct idr *idp, unsigned int gfp_mask);
每次通过idr获得ID号之前,需要先分配内存。
返回0表示错误,非零值代表正常
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
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;}
void *idr_find(struct idr *idp, int id);
返回值是和给定id相关联的指针,如果没有,则返回NULL
要删除一个ID,使用:
void idr_remove(struct idr *idp, int id);
下面,我们通过分析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是当前系统允许的动态总线号的最大值 */res = idr_get_new_above(&i2c_adapter_idr, adapter, __i2c_first_dynamic_bus_num, &id);mutex_unlock(&core_lists);if (res < 0) {if (res == -EAGAIN)goto retry;return res;}adapter->nr = id;return i2c_register_adapter(adapter);
}
EXPORT_SYMBOL(i2c_add_adapter);/* 采用静态总线号声明并注册一个i2c适配器(adapter)*/
int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{int id;int status;if (adap->nr & ~MAX_ID_MASK)return -EINVAL;
retry:if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)return -ENOMEM;mutex_lock(&core_lists);/* "above" here means "above or equal to", sigh;* we need the "equal to" result to force the result*/status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);if (status == 0 && id != adap->nr) {status = -EBUSY;idr_remove(&i2c_adapter_idr, id);}mutex_unlock(&core_lists);if (status == -EAGAIN)goto retry;if (status == 0)status = i2c_register_adapter(adap);return status;
}
EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);/* 注销一个i2c适配器 */
int i2c_del_adapter(struct i2c_adapter *adap)
{.../* free bus id */idr_remove(&i2c_adapter_idr, adap->nr);...return res;
}
EXPORT_SYMBOL(i2c_del_adapter);/* 通过ID号获得i2c_adapter设备结构体 */
struct i2c_adapter* i2c_get_adapter(int id)
{struct i2c_adapter *adapter;mutex_lock(&core_lists);adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);if (adapter && !try_module_get(adapter->owner))adapter = NULL;mutex_unlock(&core_lists);return adapter;
}
EXPORT_SYMBOL(i2c_get_adapter);
浅析linux内核中的idr机制相关推荐
- Linux内核中的platform机制
Linux内核中的platform机制 从Linux 2.6起引入了一套新的驱动管理和注册机制:platform_device和platform_driver.Linux中大部分的设备驱动,都可以使用 ...
- linux内核定时器死机,浅析linux内核中timer定时器的生成和sofirq软中断调用流程
浅析linux内核中timer定时器的生成和sofirq软中断调用流程 mod_timer添加的定时器timer在内核的软中断中发生调用,__run_timers会spin_lock_irq(& ...
- linux 信号优先级,linux内核中的信号机制
linux内核中的信号机制--信号处理 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blog.csdn.net ...
- Linux内核中的RCU机制
http://blog.chinaunix.net/uid-23769728-id-3080134.html RCU的设计思想比较明确,通过新老指针替换的方式来实现免锁方式的共享保护.但是具体到代码的 ...
- 深入理解 Linux 内核中的 RCU 机制
RCU(Read-Copy Update),是 Linux 中比较重要的一种同步机制.顾名思义就是"读,拷贝更新",再直白点是"随意读,但更新数据的时候,需要先复制一份副 ...
- linux做预警机制,预警通告:Linux内核中TCP SACK机制远程DoS
漏洞描述 2019年6月18日,RedHat官网发布报告:安全研究人员在Linux内核处理TCP SACK数据包模块中发现了三个漏洞,CVE编号为CVE-2019-11477.CVE-2019-114 ...
- linux通过信号回调函数,信号机制的管理结构 - Linux内核中的信号机制_Linux编程_Linux公社-Linux系统门户网站...
信号只是一个数字,数字为0-31表示不同的信号,如下表所示. 编号 信号名 默认动作 说明 1 SIGHUP 进程终止 终端断开连接 2 SIGINT 进程终止 用户在键盘上按下CTRL+C 3 SI ...
- linux内核层是什么,从用户层到内核层 - Linux内核中的信号机制_Linux编程_Linux公社-Linux系统门户网站...
1.简介 如果进程要处理某一信号,那么要在进程中注册该信号.注册信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系,即进程将要处理哪个进程和该信号被传递给进程时,将执行何种操作.主要有两个函 ...
- Linux内核中的同步原语:自旋锁,信号量,互斥锁,读写信号量,顺序锁
Linux内核中的同步原语 自旋锁,信号量,互斥锁,读写信号量,顺序锁 rtoax 2021年3月 在英文原文基础上,针对中文译文增加5.10.13内核源码相关内容. 1. Linux 内核中的同步原 ...
最新文章
- python3 命令行参数处理库 argparse、docopt、click、fire 简介
- 对计算机应用的认识100,计算机应用基础
- springboot 切换日志实现
- assert()函数
- linux uvc支持H264格式
- Android笔记 对话框demo大全
- 前人栽树,后人擦屁股
- Objective-C的对象模型
- Linux内核多线程——补充(各种平台下的多线程)
- LAMMPS分子动力学模拟技术及应用
- DSP(数字信号处理器)技术概要
- AI和人工智能入门级视频
- XML文档类型定义---XML Schema结构
- 佰落暑期java自学记录-11
- 华为交换机配置syslog发送_华为交换机的 syslog功能
- 如何制作出漂亮精致的思维导图?MindNow来帮你
- 【低碳发展案例研究】中国西部中小城市低碳发展研究——以泸州市为例
- Linux树莓派实战案例论文,树莓派|树莓派使用实例之:2 Pi R
- 记一次从某多多上买的斐讯N1黑盒的电视盒子刷机经历
- 【长按图片识别】uniapp vue开发时,点击图片识别—实现转发、收藏、识别图片二维码