Sto lavorando nel kernel per un po 'della mia ricerca estiva. Stiamo cercando di apportare modifiche al TCP, in calcoli RTT specifici. Quello che mi piacerebbe fare è sostituire la risoluzione di una delle funzioni in tcp_input.c con una funzione fornita da un modulo del kernel caricato in modo dinamico. Penso che ciò migliorerebbe il ritmo con cui possiamo sviluppare e distribuire la modifica.Posso sostituire una funzione del kernel Linux con un modulo?
La funzione a cui sono interessato è stata dichiarata come statica, tuttavia ho ricompilato il kernel con la funzione non statica ed esportato da EXPORT_SYMBOL. Ciò significa che la funzione è ora accessibile ad altri moduli/parti del kernel. Ho verificato questo da "cat/proc/kallsyms".
Ora mi piacerebbe essere in grado di caricare un modulo che può riscrivere l'indirizzo del simbolo dalla funzione iniziale a quella caricata dinamicamente. Allo stesso modo, quando il modulo deve essere scaricato, ripristinerebbe l'indirizzo originale. È un approccio fattibile? Avete tutti dei suggerimenti su come questo potrebbe essere meglio implementato?
Grazie!
Uguale Overriding functionality with modules in Linux kernel
Edit:
Questo era il mio approccio eventuale.
Data la seguente funzione (che ho voluto ignorare, e non viene esportato):
static void internal_function(void)
{
// do something interesting
return;
}
modificare in questo modo:
static void internal_function_original(void)
{
// do something interesting
return;
}
static void (*internal_function)(void) = &internal_function_original;
EXPORT_SYMBOL(internal_function);
Questo ridefinisce l'identificatore funzione prevista, invece, come un puntatore a funzione (che può essere chiamato in modo simile) indicando l'implementazione originale. EXPORT_SYMBOL() rende l'indirizzo globalmente accessibile, quindi possiamo modificarlo da un modulo (o da un'altra posizione del kernel).
ora è possibile scrivere un modulo del kernel con la seguente forma:
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;
}
Questo modulo sostituisce l'implementazione originale con una versione caricata dinamicamente. Al momento dello scaricamento, il riferimento originale (e l'implementazione) viene ripristinato. Nel mio caso specifico, ho fornito un nuovo stimatore per RTT in TCP. Usando un modulo, sono in grado di apportare piccole modifiche e riavviare i test, il tutto senza dover ricompilare e riavviare il kernel.
Ho finito per seguire il percorso suggerito nell'aggiunta di un hook globale. È stato facile da implementare e ha fornito esattamente ciò di cui avevo bisogno. Grazie per le informazioni sulla risoluzione dei simboli. Non avevo trovato una fonte che spiegasse in modo definitivo come e quando è stata aperta la tabella dei simboli (ad ogni chiamata di funzione o solo al collegamento). Questo è stato un utile consiglio. –