2012-07-13 7 views
5

Estoy modificando un kernel de Linux para agregar alguna funcionalidad al servidor virtual de Linux (LVS).¿Cómo usar los símbolos exportados opcionalmente solo si están presentes en un módulo Kernel de Linux insólito?

Desarrollé un módulo (al que llamé net/netfilter/ipvs/ip_vs_utils.c) con algunas funciones que se utilizarán para equilibrar la carga. Todas las funciones aquí se exportan usando EXPORT_SYMBOL().

Este módulo, lógicamente no está cargado todo el tiempo. Mi intención es permitir que el usuario decida si quiere usar esta funcionalidad adicional o no (cargando o descargando el módulo).

Mi pregunta es ¿cómo podría invocar estas funciones opcionalmente, (dependiendo de si el módulo está funcionando o no) de un módulo existente (y, por supuesto modificado) (net/netfilter/ipvs/ip_vs_core.c). Algo como esto:

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

respuesta de Lai es bastante bueno si sus 'if (ip_vs_utils) 'código está destinado a estar en el kernel todo el tiempo; pero si ese código está ubicado en otro módulo cargable, probablemente la mejor opción sea la dependencia simple del módulo. Ver 'depmod (8)' para detalles completos. – sarnold

Respuesta

4

creo que necesitas una cama elástica siempre (o casi siempre) cargado en el kernel.

En código de trampolín, necesita tales variables.

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***** */ 

cuando se carga el ip_vs_utils, es necesario para inicializar todas las variables, el código de inicialización en 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; 

y añadir las funciones de trampolín en el código de trampolín:

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() es necesario para proteger el módulo para que no se descargue repentinamente mientras se invoca ip_vs_utils_afunc_ptr(). También puede usar RCU para reducir la sobrecarga de try_module_get()/module_put(). (Pero es difícil)

O bien, se puede utilizar un poco de trampolín-Hack como enlace dinámico en el espacio de usuario (puede que tenga que cambiar mucho en el núcleo de Linux)

+0

Muchas gracias por su respuesta, creo que esto funcionará para mí. Sólo una pregunta. ¿Qué sucede si mi módulo ip_vs_utils se carga antes que los demás? ¿La línea 'ip_vs_utils_afunc_ptr = ip_vs_utils_afunc_impl;' no arrojará un error porque ip_vs_utils_afunc_ptr aún no está en la tabla de símbolos? – marcocamejo

+1

En este caso, es posible que deba anticipar que el trampolín está vinculado al kernel (o un módulo que siempre se carga mientras se inicia el sistema). El trampolín suele ser extremadamente más pequeño que la implementación real, está bien hacerlo siempre cargado. –

+0

Lo hizo de esta manera. ¡De nuevo muchas gracias! – marcocamejo

Cuestiones relacionadas