尝试使用lockdep功能
为了实际运行lockdep功能,向内核中添加“带有bug”的锁定处理的代码,查看bug是怎样检测出来的。
请看下面的代码,其中刻意地设置了AB←→BA死锁。
/Lockdep test code/
static DEFINE_SPINLOCK(hack_spinA);
static DEFINE_SPINLOCK(hack_spinB);
void hack_spinAB(void)
{
printk(KERN_ERR"hack_lockdep:A->B\n");
spin_lock(&hack_spinA);
spin_lock(&hack_spinB);
spin_unlock(&hack_spinB);
spin_unlock(&hack_spinA);
}
void hack_spinBA(void)
{
printk(KERN_ERR"hack_lockdep:B->A\n");
spin_lock(&hack_spinB);
spin_lock(&hack_spinA);
spin_unlock(&hack_spinB);
spin_unlock(&hack_spinA);
}
void hack_lockdep_test(void)
{
hack_spinAB();
hack_spinBA();
}
这段代码包括按照A→B、B→A的相反顺序获取锁的处理。因此,就存在潜在死锁的危险(hack_spinAB()和hack_spinBA()如果同时从不同的上下文中调用,则两个处理过程将互相等待而停止,造成死锁)。
这些反序的调用是由hack_lockdep_test()函数来进行的。实际运行这个处理过程时需要将向hack_lockdep_test()函数的调用添加到内核中。添加的位置可以设置为init/main.c的kernel_init()函数(必须在lockdep_init()的调用之后)。
extern void hack_lockdep_test(void);
static int__init kernel_init(void*unused)
{
lock_kernel();
/*
*init can run on any cpu.
*/
:
if(sys_access((const char__user*)ramdisk_execute_command,0)!=0)
{
ramdisk_execute_command=NULL;
prepare_namespace();
}
hack_lockdep_test();
/*
*Ok, we have completed the initial bootup, and
*we're essentially up and running.Get rid of the
*initmem segments and start the user-mode stuff..
*/
init_post();
return 0;
}
在进行了上述修改的内核中启动系统,在启动中就会检测并指出存在发生死锁的危险,如下所示。
在测试代码中只是将这些函数依次调用,因此并不会发生死锁。但是,内核注意到两个锁按照反序调用,并指出这段代码违反了避免死锁的规则。