如果导出的符号存在于内置Linux内核模块中,如何选择使用它们?
我正在修改Linux内核以向Linux虚拟服务器(LVS)添加一些功能 我开发了一个模块(我称之为如果导出的符号存在于内置Linux内核模块中,如何选择使用它们?,linux,linux-kernel,kernel-module,Linux,Linux Kernel,Kernel Module,我正在修改Linux内核以向Linux虚拟服务器(LVS)添加一些功能 我开发了一个模块(我称之为net/netfilter/ipvs/ip_vs_utils.c),其中包含一些用于负载平衡的函数。这里的所有函数都是使用EXPORT\u SYMBOL()导出的 逻辑上,此模块并非始终加载。我的意图是允许用户决定是否要使用此附加功能(加载或卸载模块) 我的问题是如何从现有(当然是修改过的)模块(net/netfilter/ipvs/ip_vs_core.c)选择性地调用这些函数(取决于模块是否正在
net/netfilter/ipvs/ip_vs_utils.c
),其中包含一些用于负载平衡的函数。这里的所有函数都是使用EXPORT\u SYMBOL()
导出的
逻辑上,此模块并非始终加载。我的意图是允许用户决定是否要使用此附加功能(加载或卸载模块)
我的问题是如何从现有(当然是修改过的)模块(net/netfilter/ipvs/ip_vs_core.c
)选择性地调用这些函数(取决于模块是否正在运行)。大概是这样的:
if(ip_vs_utils_IsLoaded)
{
function1(arg1, arg2, arg3); // being function1 defined on ip_vs_utils.c
}
我想你需要一个蹦床总是(或者几乎总是)加载到内核中 在trampoline代码中,您需要修改这些变量
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***** */
加载ip_vs_utils时,需要初始化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;
并在蹦床代码中添加蹦床功能:
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()来防止在调用ip_vs_utils_afunc_ptr()时突然卸载模块。
您也可以使用RCU来减少try\u module\u get()/module\u put()的开销。(但这很难)
或者你可以在用户空间中使用一些蹦床黑客,比如动态链接(你可能需要在linux内核中做很多更改)非常感谢你的回答,我想这对我来说很有用。只是个问题。如果我的模块ip_vs_utils先于其他模块加载,会发生什么情况?行
ip_vs_utils_afunc_ptr=ip_vs_utils_afunc_代码>抛出错误,因为ip_vs_utils_afunc_ptr还不在符号表中?在这种情况下,您可能需要将蹦床链接到内核(或系统启动时始终加载的模块)之前。trampoline通常比实际的实现小得多,让它总是被加载是可以的。如果你的if(ip\u vs\u utils)
代码一直都在内核中,Lai的答案是非常好的;但是,如果代码本身位于另一个可加载模块中,那么简单的模块依赖性可能是更好的方法。有关详细信息,请参见depmod(8)
。