Могу ли я заменить функцию ядра Linux модулем?
Я начинаю работу над ядром для небольшого количества моих летних исследований. Мы надеемся внести изменения в TCP, в конкретные расчеты RTT. Я хотел бы заменить разрешение одной из функций в tcp_input.c на функцию, предоставляемую динамически загружаемым модулем ядра. Я думаю, что это улучшило бы скорость, с которой мы можем разрабатывать и распространять модификацию.
Интересующая меня функция была объявлена как статическая, однако я перекомпилировал ядро с нестатической функцией и экспортировал ее в 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. Используя модуль, я могу вносить небольшие изменения и перезапускать тестирование без необходимости перекомпиляции и перезагрузки ядра.