一般来说对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的符号,这些符号来自netmampmp软件包,该软件包在SNMPmath可加载模块中引用。
我的问题既笼彻又具体。什么是正确的方法 - 可加载模块调用的这个库应该被强制进入可加载模块吗?是否应该强制进入测试程序(尽管没有编译时参考)?或者它应该在可加载模块中动态加载(这似乎与我在其他示例中看到的相矛盾)?
在任何一种情况下,如何修改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
现在将按预期运行。我发现在构建我的时候链接到netsnmp库的so文件似乎有效。
但这是正确的顺序吗?和/或首选序列?
聚苯乙烯。关闭在第一个提议的答案中阅读论文。
答案 0 :(得分:2)
解释指针:Drepper's paper: Howto write shared libraries
但我们需要更多源代码(以及用于编译它的命令),以及真正的错误消息(例如dlerror()
调用后dlopen
给出的)以帮助更多。
(另见this answer)
您可能希望将-lsomething
(我不知道哪些,您可能知道!)这些库添加到正在构建gcc -shared
的命令SNMPmath.so
中....您不希望将libsnmp.a
之类的静态库链接到它(您应该将共享库链接到SNMPmath.so
共享对象)。