linux CONFIG_DEBUG_OBJECTS 用法

该选项用来开启debugobjects模块,对应内核代码中的debugobjects.c,
这个模块是个通用的调试框架,用来跟踪object的生命周期。
kernel中已有的应用该功能的object有timer,workqueue等,
当然自己也可以定义自己的模块使用这个调试功能。


一个object有下面几种状态:
enum debug_obj_state {
ODEBUG_STATE_NONE,
ODEBUG_STATE_INIT,
ODEBUG_STATE_INACTIVE,
ODEBUG_STATE_ACTIVE,
ODEBUG_STATE_DESTROYED,
ODEBUG_STATE_NOTAVAILABLE,
ODEBUG_STATE_MAX,
};


对外提供的几个接口如下,这几个接口用于检测当前object状态是否正常,
比如debug_object_activate检查object是否处于active状态,如果object还未init或者
已经deactive,就报警告信息。
extern void debug_object_init      (void *addr, struct debug_obj_descr *descr);
extern void
debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr);
extern void debug_object_activate  (void *addr, struct debug_obj_descr *descr);
extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr);
extern void debug_object_destroy   (void *addr, struct debug_obj_descr *descr);
extern void debug_object_free      (void *addr, struct debug_obj_descr *descr);
extern void debug_object_assert_init(void *addr, struct debug_obj_descr *descr);


下面看下具体代码实现。




/**
 * debug_object_init - debug checks when an object is initialized
 * @addr: address of the object
 * @descr: pointer to an object specific debug description structure
 */
 /*
 用于告知object已被初始化 , 当该object正在被使用 , 或者是之前已被销毁 , 
 那么debugobject会给出warning , 同时 , 如果外部模块提供修正接口 , 
 debugobject会尝试修正 . 当然如果该object是第一次初始化 , 
 那么debugobject会将其状态置位已初始化 . 这里需要注意的是 , 
 该接口用于那些分配在heap上的object , 如果debugobject发现该object 在调用者的stack上 , 
 同样会给出warning .
 */
void debug_object_init(void *addr, struct debug_obj_descr *descr)
{
if (!debug_objects_enabled)
return;


__debug_object_init(addr, descr, 0);
}


static void
__debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
{
enum debug_obj_state state;
struct debug_bucket *db;
struct debug_obj *obj;
unsigned long flags;


fill_pool();//填充poll


db = get_bucket((unsigned long) addr);//获取bucket


raw_spin_lock_irqsave(&db->lock, flags);


obj = lookup_object(addr, db);//从bucket中查找obj
if (!obj) {//查找失败就重新申请一个object
obj = alloc_object(addr, db, descr);
if (!obj) {
debug_objects_enabled = 0;
raw_spin_unlock_irqrestore(&db->lock, flags);
debug_objects_oom();//分配内存失败的话,需要释放静态申请的obj
return;
}
debug_object_is_on_stack(addr, onstack);
}


switch (obj->state) {
case ODEBUG_STATE_NONE:
case ODEBUG_STATE_INIT:
case ODEBUG_STATE_INACTIVE:
obj->state = ODEBUG_STATE_INIT;
break;
//obj处于active时,再调用此函数就会报警告信息
case ODEBUG_STATE_ACTIVE:
debug_print_object(obj, "init");
state = obj->state;
raw_spin_unlock_irqrestore(&db->lock, flags);
//执行注册的修复函数
debug_object_fixup(descr->fixup_init, addr, state);
return; 


case ODEBUG_STATE_DESTROYED:   // init一个已经销毁的obj
debug_print_object(obj, "init");
break;
default:
break;
}


raw_spin_unlock_irqrestore(&db->lock, flags);
}
//obj_pool是保存obj node hash list,
//这个函数检查如果初始化申请的obj数量少于ODEBUG_POOL_MIN_LEVEL,就会继续
//申请object,然后加入obj_pool中
static void fill_pool(void)
{
gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
struct debug_obj *new;
unsigned long flags;


if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))
return;


if (unlikely(!obj_cache))
return;
//pool中obj数量过少就会申请新的obj并加入pool中
while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) {


new = kmem_cache_zalloc(obj_cache, gfp);
if (!new)
return;


kmemleak_not_leak(new);
raw_spin_lock_irqsave(&pool_lock, flags);
hlist_add_head(&new->node, &obj_pool);
obj_pool_free++;
raw_spin_unlock_irqrestore(&pool_lock, flags);
}
}


/*
 * We use the pfn of the address for the hash. That way we can check
 * for freed objects simply by checking the affected bucket.
 */
//计算object地址对应的hash值,同一个page内的addr,计算出来的hash值相同
//object hash后保存在bucket list中,便于后续查找
static struct debug_bucket *get_bucket(unsigned long addr)
{
unsigned long hash;
//同一个page内的addr,计算出来的hash值相同
hash = hash_long((addr >> ODEBUG_CHUNK_SHIFT), ODEBUG_HASH_BITS);
return &obj_hash[hash];
}


/*
 * Lookup an object in the hash bucket.
 */
 //bucket中查找某个object
static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b)
{
struct debug_obj *obj;
int cnt = 0;


hlist_for_each_entry(obj, &b->list, node) {
cnt++;
if (obj->object == addr)
return obj;
}
if (cnt > debug_objects_maxchain)
debug_objects_maxchain = cnt;


return NULL;
}


//从obj_pool中去第一个obj使用,给obj赋值,同时将obj加入hash对应的bucket list中
static struct debug_obj *
alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
{
struct debug_obj *obj = NULL;


raw_spin_lock(&pool_lock);
if (obj_pool.first) {
obj    = hlist_entry(obj_pool.first, typeof(*obj), node);


obj->object = addr;
obj->descr  = descr;
obj->state  = ODEBUG_STATE_NONE;
obj->astate = 0;
hlist_del(&obj->node);


hlist_add_head(&obj->node, &b->list);//头插法


obj_pool_used++;
if (obj_pool_used > obj_pool_max_used)
obj_pool_max_used = obj_pool_used;


obj_pool_free--;
if (obj_pool_free < obj_pool_min_free)
obj_pool_min_free = obj_pool_free;
}
raw_spin_unlock(&pool_lock);


return obj;
}


//这个函数用的比较多,用来打印object state 冲突信息
static void debug_print_object(struct debug_obj *obj, char *msg)
{
struct debug_obj_descr *descr = obj->descr;
static int limit;


if (limit < 5 && descr != descr_test) {
void *hint = descr->debug_hint ?
descr->debug_hint(obj->object) : NULL;
limit++;
WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) "
"object type: %s hint: %pS\n",
msg, obj_states[obj->state], obj->astate,
descr->name, hint);
}
debug_objects_warnings++;
}
总结来看就是初始化时先申请了512个obj,加入到obj_pool,需要用到obj时就从
obj_pool中取,然后用user定义的object地址计算hash值,将obj加入到对应的bucket hash list中。


其他几个接口用法类似,简单描述下接口用法,就不再详细分析代码了。


/**
 * debug_object_activate - debug checks when an object is activated
 * @addr: address of the object
 * @descr: pointer to an object specific debug description structure
 */
 /*
 告知object正在被使用 , 如果该object已经被使用 , 或者之前已被销毁, 
 那么debugobject会给出warning , 并尝试修正 
 */
void debug_object_activate(void *addr, struct debug_obj_descr *descr)
 
/**
 * debug_object_deactivate - debug checks when an object is deactivated
 * @addr: address of the object
 * @descr: pointer to an object specific debug description structure
 */
 /*
 告知object停止使用 , 如果该object已经被停用 , 或者已被销毁 , 
 那么debugobject会给出warning
 */
void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)




/**
 * debug_object_destroy - debug checks when an object is destroyed
 * @addr: address of the object
 * @descr: pointer to an object specific debug description structure
 */
 /*
 告知object被销毁 , 如果该object正在被使用 , 或者已被销毁 , 
 那么会给出warning , 并尝试修正该错误 


 */
void debug_object_destroy(void *addr, struct debug_obj_descr *descr)




/**
 * debug_object_free - debug checks when an object is freed
 * @addr: address of the object
 * @descr: pointer to an object specific debug description structure
 */
 /*
 告知object被释放 , 如果该object正在被使用 ,
 那么会给出warning , 并尝试修正该错误 . 
 同时该接口还会将object在中 的记录移除


 */
void debug_object_free(void *addr, struct debug_obj_descr *descr)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值