我是这样调试kernel的race condition的, 超有用

    xiaoxiao2026-04-04  6

    内核调试中, 经常会有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环境来验证问题

    最新回复(0)