内核调试中, 经常会有race, 方便的调试方法可以手动造一个环境出来模拟一下我们想要的时序, 来验证想法.
-
- *
比如说, a, b, 2个task, 想让a跑到某行指令的时候, 暂停运行, 然后让b运行来尝试进入共有的临界区,
一种最简单的想法就是在a的代码中加入sleep,
sleep其实会引发调度, 所以就改成while 1,
改成while 1, 其他task跑到这里的时候也会生效,
所以加if条件语句,
这些方法公有的缺点都是需要改代码, 重新编译,
下面是一种不用改代码的方法
-
- *
首先设置断点, 然后程序中断到这里之后, 把rip的值改到一个while 1里面去
比如现在task 9171停到了kswapd_try_to_sleep+281
然后把rip改成bogus_64_magic去
然后让系统继续跑
(gdb) p $lx_current()->pid
$3 = 9171
(gdb) p $rip
$4 = (void (*)()) 0xffffffff81182679 <kswapd_try_to_sleep+281>
(gdb) x/i bogus_64_magic
0xffffffff81049427 <bogus_64_magic>: jmp 0xffffffff81049427 <bogus_64_magic>
(gdb) p $rip = bogus_64_magic
$5 = (void (*)()) 0xffffffff81049427 <bogus_64_magic>
(gdb)
(gdb)c
这样task 9171就相当于在某条指令之后就不跑了, cpu占用100, 符合预期
9171 root 20 0 0 0 0 S 100.0
-
- *
然后执行task b的命令, 爱跑什么跑什么
然后就是把task a回来接着跑, 刚才是在kswapd_try_to_sleep+281中断的, 那现在就回到这里, 然后继续跑就可以了
(gdb) c
Continuing.
Thread 8 received signal SIGINT, Interrupt.
bogus_64_magic () at arch/x86/kernel/acpi/wakeup_64.S:39
(gdb) p $rip = kswapd_try_to_sleep+281
$6 = (void (*)()) 0xffffffff81182679 <kswapd_try_to_sleep+281>
(gdb) c
Continuing.
就可以很方便的构造race环境来验证问题