尝试使用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;

}


在进行了上述修改的内核中启动系统,在启动中就会检测并指出存在发生死锁的危险,如下所示。

尝试使用lockdep功能 - 图1

尝试使用lockdep功能 - 图2

在测试代码中只是将这些函数依次调用,因此并不会发生死锁。但是,内核注意到两个锁按照反序调用,并指出这段代码违反了避免死锁的规则。