Czy mogę zastąpić funkcję jądra Linuksa modułem?

Wchodzę do pracy z jądrem przez trochę moich letnich badań. Chcemy wprowadzić modyfikacje TCP w konkretnych obliczeniach RTT. Chciałbym zastąpić rozdzielczość jednej z funkcji w tcp_input.c funkcją dostarczaną przez dynamicznie ładowany moduł jądra. Myślę, że poprawiłoby to tempo rozwoju i dystrybucji modyfikacji.

Funkcja, która mnie interesuje, została zadeklarowana jako statyczna, jednak ponownie skompilowałem jądro z funkcją niestatyczną i wyeksportowaną przez EXPORT_SYMBOL. Oznacza to, że funkcja jest teraz dostępna dla innych modułów / części jądra. Sprawdziłem to przez „cat / proc / kallsyms”.

Teraz chciałbym móc załadować moduł, który może przepisać adres symbolu z początkowej na dynamicznie ładowaną funkcję. Podobnie, gdy moduł ma zostać rozładowany, przywróci oryginalny adres. Czy to możliwe podejście? Czy wszyscy macie sugestie, w jaki sposób można to lepiej wdrożyć?

Dzięki!

Taki sam jakNadpisywanie funkcjonalności za pomocą modułów w jądrze Linux

Edytować:
To było moje ostateczne podejście.
Biorąc pod uwagę następującą funkcję (którą chciałem zastąpić i nie jest eksportowana):

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

zmodyfikuj w ten sposób:

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

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

Zmienia to zamiast tego oczekiwany identyfikator funkcji jako wskaźnik funkcji (który można wywołać w podobny sposób) wskazując na pierwotną implementację. EXPORT_SYMBOL () sprawia, że ​​adres jest globalnie dostępny, więc możemy go zmodyfikować z modułu (lub innej lokalizacji jądra).

Teraz możesz napisać moduł jądra o następującej formie:

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

Moduł ten zastępuje oryginalną implementację wersją ładowaną dynamicznie. Po rozładowaniu przywracane jest oryginalne odwołanie (i implementacja). W moim konkretnym przypadku udostępniłem nowy estymator dla RTT w TCP. Korzystając z modułu, jestem w stanie dokonać drobnych poprawek i ponownie uruchomić testowanie, wszystko bez konieczności ponownej kompilacji i ponownego uruchomienia jądra.

questionAnswers(4)

yourAnswerToTheQuestion