Ubuntu C程序可加载模块和未定义符号
一般来说,它对linux非常陌生,试图构建一个可加载的模块以供zabbix使用,这是可行的,但试图构建一个简单的shell程序来测试它。这意味着这个模块需要动态加载 可共享模块SNMPmath由以下内容构建:Ubuntu C程序可加载模块和未定义符号,c,linux,C,Linux,一般来说,它对linux非常陌生,试图构建一个可加载的模块以供zabbix使用,这是可行的,但试图构建一个简单的shell程序来测试它。这意味着这个模块需要动态加载 可共享模块SNMPmath由以下内容构建: gcc -shared -o SNMPmath.so $(CFLAGS) -I../../../include -I/usr/include/libxml2 -fPIC SNMPmath.c 这对zabbix很有效 测试程序(TestSO.c)使用 要动态加载此映像,当它加载时,会
gcc -shared -o SNMPmath.so $(CFLAGS) -I../../../include -I/usr/include/libxml2 -fPIC SNMPmath.c
这对zabbix很有效
测试程序(TestSO.c)使用
要动态加载此映像,当它加载时,会丢失一些符号,包括来自SNMPmath可加载模块中引用的net snmp包的init_snmp
我的问题既一般又具体。正确的方法是什么——这个由可加载模块调用的库应该强制进入可加载模块吗?它是否应该强制进入测试程序(尽管没有编译时引用)?或者它应该在可加载模块中动态加载(这似乎与我在其他示例中看到的相反)
在这两种情况下,如何修改GCC命令以包含netsnmp?我尝试了整个归档的各种变体,不需要,列出了我认为是库(/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
#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.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;
}
下面是主要程序:
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
#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;
}
现在将按预期运行。我发现在构建so时,针对netsnmp库的so文件进行链接似乎是可行的
但这是正确的顺序吗?和/或首选序列
附:阅读第一个建议答案中的论文。指向解释的指针:
但是我们需要更多的源代码(以及用于编译它的命令)和真正的错误消息(例如,dlerror()
afterdlopen
call)来提供更多帮助
(另见)
您可能希望将一些库添加到正在构建
SNMPmath的命令gcc-shared
,例如-lsomething
(我不知道是哪个,您可能知道!)。。。。您不想将像libsnmp.a
这样的静态库链接到它(您应该将共享库链接到您的SNMPmath.so
共享对象)。显示更多的C源代码。+1表示明确的问题,不过,我同意@BasileStarynkevitch的观点,即发布一些额外的代码将增加您获得有用答案的几率。自最初发布以来,我已经做了一些进一步的工作,但将使用当前设置对其进行编辑。我试图避免一堆与zabbix相关的无关代码,在我发布之前,让我看看是否可以缩减它。谢谢。我正在费力地阅读那份文件。它似乎确实起作用了,您对我修复它的方式有什么意见吗,特别是如果链接器选项在附带的程序中显示正确(理所当然地认为我使用的库是正确的库)?
TestSO: TestSO.c
gcc -rdynamic -o TestSO -I../../../include -I/usr/include/libxml2 TestSO.c -ldl