28

そのため、どのカーネル プロセスがブロック ドライバーでいくつかの関数を呼び出しているかを調べようとしています。C ライブラリに backtrace() を含めると簡単になると思いました。しかし、バックトレースの読み込みに問題があります。

このサンプル関数をコピーして、バックトレースを表示しました。

http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/063/6391/6391l1.html

コンパイルしようとすると、どこかでファイルが見つからないか、関数が定義されていないというエラーが発生します。

これが最も近いものです。

Makefile では、コンパイラ ディレクティブを次のように記述します。

 -rdynamic -I/usr/include 

2 番目の -I/usr/include を省略した場合、コンパイラは、必要なヘッダー execinfo.h が見つからないと報告します。

次に、バックトレースを実行するコードで、例から関数をコピーしました。

//trying to include the c backtrace capability
#include <execinfo.h>

void show_stackframe() {
void *trace[16];
char **messages = (char **)NULL;
int i, trace_size = 0;

trace_size = backtrace(trace, 16);
messages = backtrace_symbols(trace, trace_size);
printk(KERN_ERR "[bt] Execution path:\n");
for (i=0; i<trace_size; ++i)
    printk(KERN_ERR "[bt] %s\n", messages[i]);
}
//backtrace function

エラーの最初の兆候が発生するブロックドライバー関数で、後でこの関数の呼び出しを行いました。単に:

show_stackframe();

したがって、コンパイルすると、次のエラーが発生します。

user@slinux:~/2.6-32$ make -s
Invoking make againt the kernel at /lib/modules/2.6.32-5-686/build
In file included from /usr/include/features.h:346,
        from /usr/include/execinfo.h:22,
        from /home/linux/2.6-32/block/block26.c:49:
/usr/include/sys/cdefs.h:287:1: warning: "__always_inline" redefined
In file included from /usr/src/linux-headers-2.6.32-5-common/include/linux/compiler-gcc.h:86,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/compiler.h:40,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/stddef.h:4,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/list.h:4,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/module.h:9,
        from /home/linux/2.6-32/inc/linux_ver.h:40,
        from /home/linux/2.6-32/block/block26.c:32:
/usr/src/linux-headers-2.6.32-5-common/include/linux/compiler-gcc4.h:15:1: warning: this is the location of the previous definition
    /home/linux/2.6-32/block/block26.c:50: warning: function declaration isn’t a prototype
WARNING: "backtrace" [/home/linux/2.6-32/ndas_block.ko] undefined!
WARNING: "backtrace_symbols" [/home/linux/2.6-32/ndas_block.ko] undefined!

注: block26.c は、バックトレースを取得したいファイルです。

backtrace と backtrace_symbols が .ko モジュールにコンパイルされたときに未定義のままになる明白な理由はありますか?

コンピューターに常駐し、モジュールにロードされていないコンパイラー・インクルード execinfo.h を使用しているため、推測しています。

控えめに言っても、私の無知な推測です。

バックトレース関数をモジュールにロードするのを手伝ってくれる人はいますか?

このお問い合わせをご覧いただきありがとうございます。

私はデビアンに取り組んでいます。関数などを取り出すと、モジュールは正常にコンパイルされ、ほぼ完全に動作します。

ndasusers から

4

4 に答える 4

52

スタックの内容とバックトレースをカーネル ログに出力するにdump_stack()は、カーネル モジュールで関数を使用します。linux/kernel.hこれは、カーネル ソース ディレクトリの include フォルダーで宣言されています。

于 2011-05-03T06:34:37.753 に答える
22

スタックトレースを保存してその要素を何らかの方法で処理する必要がある場合、save_stack_trace()またはそれdump_trace()もオプションかもしれません。これらの関数は、それぞれ<linux/stacktrace.h>およびで宣言されて<asm/stacktrace.h>います。

これらを使用するのは簡単ではありませんdump_stack()が、より柔軟性が必要な場合に役立つ場合があります。

の使用方法save_stack_trace()は次のとおりです (必要に応じた値に置き換えHOW_MANY_ENTRIES_TO_STOREてください。通常は 16 ~ 32 で十分です)。

unsigned long stack_entries[HOW_MANY_ENTRIES_TO_STORE];
struct stack_trace trace = {
    .nr_entries = 0,
    .entries = &stack_entries[0],

    .max_entries = HOW_MANY_ENTRIES_TO_STORE,

    /* How many "lower entries" to skip. */
    .skip = 0
}; 
save_stack_trace(&trace);

現在stack_entries、配列には適切な呼び出しアドレスが含まれています。埋められた要素の数は ですnr_entries

指摘するもう1つのこと。の実装に属するスタック エントリsave_stack_trace()dump_trace()またはdump_stack()それ自体を出力しないことが望ましい場合 (システムによって、このようなエントリの数は異なる場合があります)、 を使用する場合は、次のトリックを適用できますsave_stack_trace()。「アンカー」エントリとして使用__builtin_return_address(0)し、それより「低くない」エントリのみを処理できます。

于 2011-05-03T12:47:47.863 に答える