目前我正在用 C 语言在 Linux(2.6 内核)中使用 FUSE 文件系统模块开发一个应用程序。由于一些编程错误,应用程序在挂载文件系统后崩溃。由于我是 Linux/C 环境中的新手开发人员。您能否让我告诉我调试此类程序的可能选项?
5 回答
FUSE 的一些特性可能会使其难以调试:它通常在后台运行(这意味着它与 stdin/out 分离)并且是多线程的(这可能会引入竞争条件并且使用 gdb 进行调试更复杂)。幸运的是,这两个功能都可以禁用:
- 使用
-f
开关将您的应用程序保持在前台。这将使您的 printf 行工作。 - 使用
-s
开关禁用多线程。禁用多线程会限制性能,但也会隐藏某些错误(竞争条件),简化 gdb 的使用,并确保 printf 输出可读(当多个线程几乎同时调用 printf 时,它们的输出可能会混淆)。
我还建议阅读 Geoff Kuenning 的FUSE 文档。
-d
使用该选项运行您的 fuse 客户端。
首先,确保您在编译时启用了调试符号(-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 杀手采取行动、取消引用坏指针、双 free() 等。Valgrind 是一个很好的工具来捕捉它. GDB 很有帮助,但我发现 Valgrind 是不可或缺的。
UML 非常适合调试 linux 内核的通用部分,如文件系统、调度,但不适用于内核的硬件平台或驱动程序特定部分。
http://www.csee.wvu.edu/~katta/uml/x475.html
http://valerieaurora.org/uml_tips.html
并仔细查看图表:
您将看到实现所有 FUSE 回调处理程序的应用程序“hello”。所以大部分调试都是在用户空间程序中进行的,因为 FUSE 内核模块(和 libfuse)通常是供所有 FUSE 文件系统使用的。