Linux内核ida数据结构使用
Linux 内核中的 ida
(ID 分配器)是用于高效分配和释放唯一非负整数 ID 的轻量级工具,适用于只需 ID 标识而无需关联对象的场景。以下是其详细用法指南:
一、核心概念
ida
专注于ID 本身的管理(分配、释放、检查),不存储与 ID 关联的指针(区别于 idr
),适合需要唯一 ID 但无需映射对象的场景(如文件描述符、设备子编号等)。
二、使用步骤
1. 头文件与数据结构
需包含头文件 <linux/ida.h>
,核心结构体为 struct ida
:
#include <linux/ida.h>struct ida my_ida; // 定义一个 ida 实例
2. 初始化与销毁
- 初始化:使用
ida_init()
初始化ida
结构(必须在使用前调用)。 - 销毁:使用
ida_destroy()
释放资源(需确保所有 ID 已释放)。
// 初始化
ida_init(&my_ida);// 销毁(通常在模块退出时)
ida_destroy(&my_ida);
3. ID 分配
ida
提供多种分配方式,满足不同场景需求:
函数 | 功能描述 | 示例 |
---|---|---|
ida_alloc(ida, gfp) | 分配最小可用 ID(从 0 开始) | ida_alloc(&my_ida, GFP_KERNEL); |
ida_alloc_min(ida, min_id, gfp) | 分配 ≥ min_id 的最小可用 ID | ida_alloc_min(&my_ida, 100, GFP_ATOMIC); (从 100 开始) |
ida_alloc_range(ida, min, max, gfp) | 从 [min, max] 范围分配可用 ID | ida_alloc_range(&my_ida, 50, 200, GFP_KERNEL); |
4. ID 释放
使用 ida_free()
释放已分配的 ID,使其可被再次分配:
void ida_free(struct ida *ida, unsigned int id);
5. 检查 ID 状态
使用 ida_is_alloced()
检查指定 ID 是否已被分配:
bool ida_is_alloced(struct ida *ida, unsigned int id);
- 返回值:
true
表示已分配,false
表示可用。
三、并发安全处理
ida
操作不保证线程安全,多线程 / 中断上下文访问时需通过自旋锁保护:
#include <linux/spinlock.h>static DEFINE_SPINLOCK(ida_lock); // 定义自旋锁// 分配 ID(带锁)
int alloc_id_safe() {int id;unsigned long flags;spin_lock_irqsave(&ida_lock, flags); // 加锁(禁止中断)id = ida_alloc_min(&my_ida, 100, GFP_ATOMIC); // 用 GFP_ATOMIC 避免睡眠spin_unlock_irqrestore(&ida_lock, flags); // 解锁return id;
}// 释放 ID(带锁)
void free_id_safe(int id) {unsigned long flags;spin_lock_irqsave(&ida_lock, flags);ida_free(&my_ida, id);spin_unlock_irqrestore(&ida_lock, flags);
}
四、完整示例(模块中使用)
#include <linux/module.h>
#include <linux/ida.h>
#include <linux/spinlock.h>static struct ida my_ida;
static DEFINE_SPINLOCK(ida_lock);static int __init ida_demo_init(void) {int id1, id2;bool is_alloced;// 初始化 IDAida_init(&my_ida);// 分配 IDspin_lock_irq(&ida_lock);id1 = ida_alloc_min(&my_ida, 100, GFP_ATOMIC);id2 = ida_alloc_range(&my_ida, 100, 200, GFP_ATOMIC);spin_unlock_irq(&ida_lock);printk("Allocated IDs: %d, %d\n", id1, id2);// 检查 ID 状态spin_lock_irq(&ida_lock);is_alloced = ida_is_alloced(&my_ida, id1);spin_unlock_irq(&ida_lock);printk("ID %d is %s\n", id1, is_alloced ? "allocated" : "free");return 0;
}static void __exit ida_demo_exit(void) {// 释放 ID(假设 id1、id2 已保存)spin_lock_irq(&ida_lock);ida_free(&my_ida, id1);ida_free(&my_ida, id2);spin_unlock_irq(&ida_lock);// 销毁 IDAida_destroy(&my_ida);printk("IDA demo exited\n");
}module_init(ida_demo_init);
module_exit(ida_demo_exit);
MODULE_LICENSE("GPL");