I think you need a trampoline always (or almost always) loaded into the kernel.
In the trampoline code, you need such variables.
struct module *ip_vs_utils_mod;
EXPORT_SYMBOL(ip_vs_utils_mod);
ret_type (*ip_vs_utils_afunc_ptr)(func_arg_list);
EXPORT_SYMBOL(ip_vs_utils_afunc_ptr);
When ip_vs_utils loads, you need to initialize all the variables, the initialization code is in the ip_vs_utils.c file:
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;
And add trampoline functions to the trampoline code:
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 () is needed to protect the module from sudden unloading when ip_vs_utils_afunc_ptr () is called. You can also use RCU to reduce the overhead of try_module_get () / module_put (). (But it is difficult)
- -, ( Linux)