夏の研究のためにカーネルの作業に取り掛かります。特定の RTT 計算で、TCP に変更を加える予定です。私がやりたいことは、tcp_input.c 内の関数の 1 つの解決を、動的にロードされたカーネル モジュールによって提供される関数に置き換えることです。これにより、修正の開発と配布のペースが向上すると思います。
私が興味を持っている関数は静的として宣言されていましたが、非静的関数でカーネルを再コンパイルし、EXPORT_SYMBOL によってエクスポートしました。これは、関数がカーネルの他のモジュール/部分にアクセスできるようになったことを意味します。「cat /proc/kallsyms」でこれを確認しました。
ここで、シンボル アドレスをイニシャルから動的に読み込まれた関数に書き換えることができるモジュールを読み込めるようにしたいと考えています。同様に、モジュールをアンロードすると、元のアドレスが復元されます。これは実行可能なアプローチですか?これをより適切に実装するにはどうすればよいか、皆さんからの提案はありますか?
ありがとう!
Linux カーネルのモジュールによる機能のオーバーライドと同じ
編集:
これが私の最終的なアプローチでした。
次の関数を考えると(オーバーライドしたかったのですが、エクスポートされていません):
static void internal_function(void)
{
// do something interesting
return;
}
次のように変更します。
static void internal_function_original(void)
{
// do something interesting
return;
}
static void (*internal_function)(void) = &internal_function_original;
EXPORT_SYMBOL(internal_function);
これにより、期待される関数識別子が、元の実装を指す関数ポインタ (同様の方法で呼び出すことができます) として再定義されます。EXPORT_SYMBOL() は、アドレスをグローバルにアクセスできるようにするため、モジュール (または他のカーネルの場所) から変更できます。
これで、次の形式でカーネル モジュールを作成できます。
static void (*original_function_reference)(void);
extern void (*internal_function)(void);
static void new_function_implementation(void)
{
// do something new and interesting
// return
}
int init_module(void)
{
original_function_reference = internal_function;
internal_function = &new_function_implementation;
return 0;
}
void cleanup_module(void)
{
internal_function = original_function_reference;
}
このモジュールは、元の実装を動的にロードされたバージョンに置き換えます。アンロードすると、元の参照 (および実装) が復元されます。私の特定のケースでは、TCP で RTT の新しい推定器を提供しました。モジュールを使用することで、カーネルを再コンパイルして再起動することなく、小さな調整を行ってテストを再開することができます。