2012-07-13 4 views
5

Sto modificando un kernel Linux per aggiungere alcune funzionalità al Linux Virtual Server (LVS).Come utilizzare i simboli esportati opzionalmente solo se sono presenti in un modulo Kernel Linux non protetto?

Ho sviluppato un modulo (che ho chiamato net/netfilter/ipvs/ip_vs_utils.c) con alcune funzioni da utilizzare durante il bilanciamento del carico. Tutte le funzioni qui sono esportate usando EXPORT_SYMBOL().

Questo modulo, logicamente non viene caricato tutto il tempo. La mia intenzione è di consentire all'utente di decidere se desidera utilizzare questa funzionalità aggiuntiva o meno (caricamento o scaricamento del modulo).

La mia domanda è come potrei invocare queste funzioni OPZIONALMENTE (a seconda se il modulo è in esecuzione o meno) da un modulo esistente (e ovviamente modificato) (net/netfilter/ipvs/ip_vs_core.c). Qualcosa di simile a questo:

if(ip_vs_utils_IsLoaded) 
{ 
    function1(arg1, arg2, arg3); // being function1 defined on ip_vs_utils.c 
} 
+1

risposta di Lai è abbastanza buona se i vostri 'if (ip_vs_utils) 'Il codice è destinato ad essere nel kernel sempre; ma se quel codice si trova in un altro modulo caricabile, probabilmente la semplice dipendenza del modulo è l'approccio migliore. Vedi 'depmod (8)' per i dettagli completi. – sarnold

risposta

4

Penso che avete bisogno di un trampolino sempre (o quasi sempre) caricati nel kernel.

Nel codice trampolino, è necessario tali variabili.

struct module *ip_vs_utils_mod; 
EXPORT_SYMBOL(ip_vs_utils_mod); 

/* function pointers */ 
ret_type (*ip_vs_utils_afunc_ptr)(func_arg_list); /* Add static if you put it in a header file! */ 
EXPORT_SYMBOL(ip_vs_utils_afunc_ptr); /* ******EXPORTED***** */ 

Quando i ip_vs_utils viene caricato, è necessario init tutte le variabili, codice di inizializzazione in ip_vs_utils.c:

ip_vs_utils_mod = THIS_MODULE; 

/* init function pointers */ 

/* ip_vs_utils_afunc_impl is the real implementation 
* of the function, it is *****NOT***** needed to export it 
*/ 
ip_vs_utils_afunc_ptr = ip_vs_utils_afunc_impl; 

e aggiungere le funzioni trampolino nel codice trampolino:

ret_type ip_vs_utils_afunc(func_arg_list) 
{ 
    ret_type ret = DEFAULT_RET; 

    if (try_module_get(ip_vs_utils_mod)) { 
     ret = (*ip_vs_utils_afunc_ptr)(func_arg_list); 
     module_put(ip_vs_utils_mod); 
    } 
    return ret; 
} 

try_module_get() è necessario per proteggere il modulo dall'essere improvvisamente scaricato mentre viene invocato ip_vs_utils_afunc_ptr(). Puoi anche usare RCU per ridurre il sovraccarico di try_module_get()/module_put(). (Ma è difficile)

Oppure si può utilizzare un po 'di trampolino-hack come collegamento dinamico nello spazio utente (potrebbe essere necessario cambiare molto nel kernel linux)

+0

Grazie mille per la risposta, penso che funzionerà per me. Solo una domanda. Cosa succede se il mio modulo ip_vs_utils viene caricato prima degli altri? La riga non 'ip_vs_utils_afunc_ptr = ip_vs_utils_afunc_impl;' genera un errore perché ip_vs_utils_afunc_ptr non si trova ancora nella tabella dei simboli? – marcocamejo

+1

In questo caso, potrebbe essere necessario che il trampolino sia collegato al kernel (o un modulo che viene sempre caricato durante l'avvio del sistema). il trampolino è in genere estremamente più piccolo dell'implementazione reale, è OK farlo sempre caricato. –

+0

Ha fatto in questo modo. Ancora una volta, grazie mille! – marcocamejo