- 论坛徽章:
- 0
|
1. idr机制
Linux的dm中对minor number采用idr机制进行管理。idr即"ID Radix",内核中通过radix树对ID进行组织和管理,是一种将整数ID和指针关联在一起的一种机制。radix树基于以二进制表示的键值的查找树,尤其适合于处理非常长的、可变长度的键值。查找时每个节点都存储有进行下一次的bit测试之前需要跳过的bit数目,查找效率比较高。
以下代码中的注释说明了idr的基本作用(lib/idr.c)
/*
* 2002-10-18 written by Jim Houston jim.houston@ccur.com
* Copyright (C) 2002 by Concurrent Computer Corporation
* Distributed under the GNU GPL license version 2.
*
* Modified by George Anzinger to reuse immediately and to use
* find bit instructions. Also removed _irq on spinlocks.
*
* Small id to pointer translation service.
*
* It uses a radix tree like structure as a sparse array indexed
* by the id to obtain the pointer. The bitmap makes allocating
* a new id quick.
*
* You call it to allocate an id (an int) an associate with that id a
* pointer or what ever, we treat it as a (void *). You can pass this
* id to a user for him to pass back at a later time. You then pass
* that id to this code and it returns your pointer.
* You can release ids at any time. When all ids are released, most of
* the memory is returned (we keep IDR_FREE_MAX) in a local pool so we
* don't need to go to the memory "store" during an id allocate, just
* so you don't need to be too concerned about locking and conflicts
* with the slab allocator.
*/
API函数主要是以下几个:
void *idr_find(struct idr *idp, int id);
int idr_pre_get(struct idr *idp, unsigned gfp_mask);
int idr_get_new(struct idr *idp, void *ptr, int *id);
int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
void idr_remove(struct idr *idp, int id);
void idr_init(struct idr *idp);
/**
* idr_get_new - allocate new idr entry
* @idp: idr handle
* @ptr: pointer you want associated with the ide
* @id: pointer to the allocated handle
*
* This is the allocate id function. It should be called with any
* required locks.
*
* If memory is required, it will return -EAGAIN, you should unlock
* and go back to the idr_pre_get() call. If the idr is full, it will
* return -ENOSPC.
*
* @id returns a value in the range 0 ... 0x7fffffff
*/
int idr_get_new(struct idr *idp, void *ptr, int *id)
{
int rv;
rv = idr_get_new_above_int(idp, ptr, 0);
/*
* This is a cheap hack until the IDR code can be fixed to
* return proper error values.
*/
if (rv disk = alloc_disk(1);
md->disk->major = _major;
md->disk->first_minor = minor;
md->disk->queue = md->queue;
sprintf(md->disk->disk_name, "dm-%d", minor);
add_disk(md->disk);
init_waitqueue_head(&md->wait);
init_waitqueue_head(&md->eventq);
}
1)对于指定minor
/*
* See if the device with a specific minor # is free.
*/
static int specific_minor(unsigned int minor)
{
int r, m;
if (minor >= (1 = (1 name);
if (r)
return r;
if (param->flags & DM_PERSISTENT_DEV_FLAG)
r = dm_create_with_minor(MINOR(huge_decode_dev(param->dev)), &md);
else
r = dm_create(&md);
}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/38597/showart_1773497.html |
|