Kann ich eine Linux-Kernelfunktion durch ein Modul ersetzen?

Ich werde für ein bisschen meiner Sommerforschung in die Kernel-Arbeit einsteigen. Wir sind bestrebt, Änderungen an der TCP in bestimmten RTT-Berechnungen vorzunehmen. Ich möchte die Auflösung einer der Funktionen in tcp_input.c durch eine Funktion ersetzen, die von einem dynamisch geladenen Kernelmodul bereitgestellt wird. Ich denke, dies würde das Tempo verbessern, mit dem wir die Modifikation entwickeln und vertreiben können.

Die Funktion, die mich interessiert, wurde als statisch deklariert, aber ich habe den Kernel mit der Funktion nicht statisch neu kompiliert und von EXPORT_SYMBOL exportiert. Dies bedeutet, dass die Funktion jetzt für andere Module / Teile des Kernels zugänglich ist. Ich habe dies durch "cat / proc / kallsyms" verifiziert.

Jetzt möchte ich in der Lage sein, ein Modul zu laden, das die Symboladresse von der Initiale zu meiner dynamisch geladenen Funktion umschreiben kann. Wenn das Modul entladen werden soll, wird auf ähnliche Weise die ursprüngliche Adresse wiederhergestellt. Ist das ein praktikabler Ansatz? Haben Sie alle Vorschläge, wie dies besser umgesetzt werden könnte?

Vielen Dank!

Gleich wieÜberschreiben der Funktionalität mit Modulen im Linux-Kernel

Bearbeiten:
Dies war mein letztendlicher Ansatz.
Dazu folgende Funktion (die ich überschreiben wollte und die nicht exportiert wird):

static void internal_function(void) 
{
  // do something interesting
  return;
}

Ändern Sie wie folgt:

static void internal_function_original(void)
{
  // do something interesting
  return;
}

static void (*internal_function)(void) = &internal_function_original;
EXPORT_SYMBOL(internal_function);

Dadurch wird der erwartete Funktionsbezeichner als Funktionszeiger (der auf ähnliche Weise aufgerufen werden kann) neu definiert, der auf die ursprüngliche Implementierung verweist. EXPORT_SYMBOL () macht die Adresse global zugänglich, sodass wir sie von einem Modul (oder einem anderen Kernel-Speicherort) aus ändern können.

Jetzt können Sie ein Kernelmodul mit der folgenden Form schreiben:

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;
}

Dieses Modul ersetzt die ursprüngliche Implementierung durch eine dynamisch geladene Version. Beim Entladen wird die ursprüngliche Referenz (und Implementierung) wiederhergestellt. In meinem speziellen Fall habe ich einen neuen Schätzer für die RTT in TCP bereitgestellt. Mit einem Modul kann ich kleine Änderungen vornehmen und die Tests neu starten, ohne den Kernel neu kompilieren und neu starten zu müssen.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage