我正在尝试调试显然导致其他的设备驱动程序 挂起的任务。决定哪个任务或在什么时间它是确定性的 会挂起。
基本上我从内核那里得到一些错误消息,说“任务有 已被阻止超过120秒“,以及一些堆栈跟踪。 挂起的任务从sendmail到mkfs到pdflush(内核线程)。 堆栈跟踪中最顶层的函数与“getnstimeofday”不同 将“bio_submit”改为“mark_locks_held”。
我很难调试这个,因为很难找到它 问题。内核提供的堆栈跟踪不是很有帮助 都不是。根据那些堆栈跟踪,其中一些挂起过程 甚至没有试图抓住锁(就像在getnstimeofday 功能),我不知道他们为什么要挂。
所以我想知道是否有人知道如何调试这样的 问题。 kgdb在这里是否有用,也许是通过给我准确的答案 指出进程挂起,它正在等待什么样的锁?
任何建议都表示赞赏。
答案 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
...
至于如何调试问题,我有两个建议:
知道某些调试输出不好,请使用您自己的代码知识来确定真正的调用堆栈。在多个堆栈转储中查找常用函数可能会有所帮助。
重新编译内核以使用帧指针。
内核仍将打印看起来像返回地址的每个值,但它会用“?”标记不可靠的地址。所以你的堆栈转储可能看起来像这样:
? printk
? A
crash
? foo
trouble