私の夏の研究のために、カーネルの作業に取り掛かりました。私たちは、特定のRTT計算でTCPを変更しようとしています。私がしたいのは、tcp_input.cの関数の1つの解決を、動的にロードされたカーネルモジュールが提供する関数に置き換えることです。私はこれが修正を開発して配布するペースを改善すると思う。Linuxカーネル機能をモジュールに置き換えることはできますか?
私が興味を持っている機能は静的であると宣言されていましたが、非静的な関数でカーネルを再コンパイルし、EXPORT_SYMBOLによってエクスポートしました。これは、関数がカーネルの他のモジュール/パーツにアクセスできるようになったことを意味します。私はこれを "cat/proc/kallsyms"で確認しました。
今や、シンボルアドレスを最初から動的にロードされた関数に書き換えることができるモジュールをロードすることができます。同様に、モジュールをアンロードするときは、元のアドレスを復元します。これは実行可能なアプローチですか?どのようにしてこれをよりうまく実装できるか、皆さんに提案がありますか?
ありがとうございます!
Overriding functionality with modules in Linux kernel
編集と同じ:
これは私の最終的なアプローチでした。
は、次の関数を考えると(私は上書きしたかったし、エクスポートされません):
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;
}
このモジュールは、動的にロードされたバージョンと元の実装を置き換えます。アンロードすると、元の参照(および実装)が復元されます。私の具体的なケースでは、私はRTTの新しい推定値をTCPに提供しました。モジュールを使用することで、カーネルを再コンパイルして再起動することなく、小さな調整と再テストを行うことができます。
グローバルフックを追加する際に提案したルートを終了しました。実装が簡単で、必要なものを正確に提供しました。 シンボル解決に関する情報をありがとう。私は、シンボルテーブルがどのようにいつアクセスされたか(各関数呼び出し時またはリンケージ時のみ)を明確に説明したソースは見つかりませんでした。これは役に立つアドバイスです。 –