【发布时间】:2014-02-11 15:45:50
【问题描述】:
一般来说,对 linux 来说非常新,并试图构建一个可加载的模块以在 zabbix 中使用,这很有效,但试图构建一个简单的 shell 程序来测试它。这意味着这个模块需要动态加载。
可共享模块 SNMPmath 是用这个构建的:
gcc -shared -o SNMPmath.so $(CFLAGS) -I../../../include -I/usr/include/libxml2 -fPIC SNMPmath.c
这对 zabbix 很有效。
测试程序(TestSO.c)使用
lib_handle = dlopen("./SNMPmath.so", RTLD_NOW);
动态加载这个图像,当它加载时,它缺少包括 init_snmp 在内的符号,这些符号来自 SNMPmath 可加载模块中引用的 net-snmp 包。
我的问题既笼统又具体。什么是正确的方法——由可加载模块调用的这个库是否应该被强制进入可加载模块?它是否应该被强制进入测试程序(尽管没有编译时引用它)?还是应该在可加载模块中动态加载它本身(这似乎与我在其他示例中看到的相矛盾)?
无论哪种情况,如何修改 GCC 命令以包含 net-snmp?我已经尝试了整个存档的变体,不需要,列出我认为是库(/usr/lib/x86_64-linux-gnu/libsnmp.a)的各种编译器选项没有效果(或偶尔出现错误) )。还尝试链接到 .so 版本(无效)。因此,关于包含该库的正确 GCC 命令的提示将非常有帮助。
这是链接主程序的一次尝试:
gcc -rdynamic -o TestSO -I../../../include -I/usr/include/libxml2 TestSO.c -ldl -Wl,--no-as-needed /usr/lib/x86_64-linux-gnu/libsnmp.so
我发现了许多加载模块的示例,但它们都加载了一个简单的例程,该例程本身没有需要满足的未定义符号。
回顾:
TestSO.c
==> Loads with dlopen SNMPmath.c
==> needs to refer to net-snmp routines like init_snmp
欢迎指点示例或解释,我意识到我遗漏了一些相当明显的东西。
在第一条评论后编辑包括:
我现在可以使用它,但如果这是正确的,我将不胜感激。我把它剪掉了,以便显示整个代码。这是生成 SO 的代码:
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <string.h>
int zbx_module_SNMPmath_avg(int i, int j)
{
init_snmp("snmpapp"); // initialize SNMP library
return 1;
}
这是它的编译方式(注意名称略有变化):
CFLAGS=-I. `net-snmp-config --cflags`
SNMPmath_small: SNMPmath_small.c
gcc -shared -o SNMPmath.so $(CFLAGS) -I../../../include -I/usr/include/libxml2 -fPIC SNMPmath_small.c -Wl,--no-as-needed,/usr/lib/x86_64-linux-gnu/libsnmp.so
然后这里是主程序:
#include <stdio.h>
#include <dlfcn.h>
#include <dlfcn.h>
#include <string.h>
int main(int argc, char **argv)
{
void *lib_handle;
int(*fn)(int req, int ret);
int x;
char *error;
lib_handle = dlopen("./SNMPmath.so", RTLD_NOW);
if (!lib_handle)
{
fprintf(stderr, "Error on open - %s\n", dlerror());
exit(1);
}
else
fprintf(stderr,"Successfully loaded module\n");
fn = dlsym(lib_handle, "zbx_module_SNMPmath_avg");
if ((error = dlerror()) != NULL)
{
fprintf(stderr, "Error on dlsym %s\n", error);
exit(1);
}
else fprintf(stderr,"Successfully called dlsym\n");
// testing
int req, ret;
req=1;
ret=1;
x=(*fn)(req, ret);
printf("Valx=%i\n",x);
dlclose(lib_handle);
return 0;
}
最后这是用:
TestSO: TestSO.c
gcc -rdynamic -o TestSO -I../../../include -I/usr/include/libxml2 TestSO.c -ldl
这现在将按预期运行。我发现在构建我的 so 时链接 netsnmp 库的 so 文件似乎可行。
但这是正确的顺序吗?和/或首选顺序?
附言。去阅读第一个建议答案中的论文。
【问题讨论】:
-
显示更多 C 源代码。
-
+1 表示明确的问题,但是我同意@BasileStarynkevitch 的观点,即发布一些额外的代码会增加您获得有用答案的几率。
-
自最初发布以来,我已经取得了一些进展,但将使用当前设置对其进行编辑。我在尽量避免一堆与zabbix相关的无关代码,让我看看我是否可以在发布之前将其削减。