内核调试挂起进程?

时间:2012-02-04 16:01:17

标签: debugging linux-kernel

我正在尝试调试显然导致其他的设备驱动程序 挂起的任务。决定哪个任务或在什么时间它是确定性的 会挂起。

基本上我从内核那里得到一些错误消息,说“任务有 已被阻止超过120秒“,以及一些堆栈跟踪。 挂起的任务从sendmail到mkfs到pdflush(内核线程)。 堆栈跟踪中最顶层的函数与“getnstimeofday”不同 将“bio_submit”改为“mark_locks_held”。

我很难调试这个,因为很难找到它 问题。内核提供的堆栈跟踪不是很有帮助 都不是。根据那些堆栈跟踪,其中一些挂起过程 甚至没有试图抓住锁(就像在getnstimeofday 功能),我不知道他们为什么要挂。

所以我想知道是否有人知道如何调试这样的 问题。 kgdb在这里是否有用,也许是通过给我准确的答案 指出进程挂起,它正在等待什么样的锁?

任何建议都表示赞赏。

1 个答案:

答案 0 :(得分:0)

当你没有在内核中启用帧指针时,堆栈跟踪将不可靠,并且让你感到困惑。内核调用扫描整个堆栈的值,这些值可能是指向内核代码的指针(即潜在的返回地址)。这意味着可能仍会打印已返回的过去函数调用。

如果您的代码如下所示:

void A(void) {
    printk("foo\n");
}

void B(void) {
    int x;
    A();
}

void crash(void) {
    char buf[32];
    *(int*)0 = 0;
}

void trouble(void) {
    int x;
    B();
    crash();
}

您的堆栈转储可能会显示如下:

printk
A
crash
foo
trouble
...

至于如何调试问题,我有两个建议:

  1. 知道某些调试输出不好,请使用您自己的代码知识来确定真正的调用堆栈。在多个堆栈转储中查找常用函数可能会有所帮助。

  2. 重新编译内核以使用帧指针。

  3. 内核仍将打印看起来像返回地址的每个值,但它会用“?”标记不可靠的地址。所以你的堆栈转储可能看起来像这样:

    ? printk
    ? A
    crash
    ? foo
    trouble