目前我正在使用Linux(2.6内核)中的FUSE文件系统模块以及C语言开发应用程序。由于某些编程错误,在挂载文件系统后,应用程序会崩溃。由于我是一个Linux/C环境的新手开发人员,你能告诉我可能调试此类程序的选项吗?
FUSE有几个功能可能会使其难以调试:它通常在后台运行(这意味着它与stdin/out分离)并且是多线程的(这可能会引入竞争条件并且使用gdb进行调试更加复杂)。幸运的是,这两个功能都可以被禁用:
-f
开关来保持应用程序在前台运行。这将使得您的 printf 行起作用。-s
开关来禁用多线程。禁用多线程将限制性能,但也会隐藏某些错误(竞争条件),简化使用gdb,并确保printf输出可读性 (当多个线程同时调用printf时,它们的输出可能会混淆)。我还建议阅读Geoff Kuenning的FUSE文档。
使用-d
选项运行您的熔断器客户端。
首先,请确保您使用调试符号编译 (-g
选项用于gcc
)。在运行程序之前,使用shell命令启用核心转储:
ulimit -c unlimited
当应用程序崩溃时,它会在当前工作目录中留下一个core
文件(只要它可以写入该文件)。
然后,您可以在gdb
调试器中加载核心文件:
gdb <executable file> <core file>
...它会显示程序崩溃的位置,并让您检查变量等内容。
您可以使用Valgrind与FUSE一起使用,但是请先阅读此文以了解关于setuid的解决方法。为方便其他需要调试我的文件系统的人,我实际上执行以下操作:
#include <valgrind/valgrind.h>
if (RUNNING_ON_VALGRIND) {
fprintf(stderr,
"******** Valgrind has been detected by %s\n"
"******** If you have difficulties getting %s to work under"
" Valgrind,\n"
"******** see the following thread:\n"
"******** http://www.nabble.com/valgrind-and-fuse-file-systems"
"-td13112112.html\n"
"******** Sleeping for 5 seconds so this doesn't fly by ....",
progname, progname);
sleep(5);
fprintf(stderr, "\n");
}
我经常在FUSE上工作...90%的时间我的崩溃是由于泄漏导致OOM killer采取行动,解除引用错误指针,双重释放等。Valgrind是一个很好的工具来捕捉这些问题。GDB也很有帮助,但我发现Valgrind是不可或缺的。
UML非常适合调试Linux内核的通用部分,如文件系统、调度等,但不适用于内核的硬件平台或驱动程序特定部分。
http://www.csee.wvu.edu/~katta/uml/x475.html
http://valerieaurora.org/uml_tips.html
仔细观察图表: