gpt4 book ai didi

c - Ubuntu C 程序可加载模块和 undefined symbol

转载 作者:太空狗 更新时间:2023-10-29 12:16:50 24 4
gpt4 key购买 nike

一般来说对 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);

动态加载此图像,当它加载时,它缺少符号,包括来自 SNMPmath 可加载模块中引用的 net-snmp 包的 init_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

我发现了许多加载模块的示例,但它们都加载了一个简单的例程,该例程本身没有需要满足的 undefined symbol 。

回顾:

    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 文件似乎可行。

但这是正确的顺序吗?和/或首选顺序?

附言。关闭以阅读第一个建议答案中的论文。

最佳答案

指向解释的指针:Drepper's paper: Howto write shared libraries

但我们需要更多的源代码(以及用于编译它的命令)和真正的错误消息(例如,在 dlopen 调用之后由 dlerror() 给出)帮助更多。

(另见 this answer)

您可能想添加一些库,例如 -lsomething(我不知道哪个,您可能知道!)到您正在构建的命令 gcc -shared SNMPmath.so ....您不想将静态库(例如libsnmp.a)链接到它(您应该将共享库链接到您的SNMPmath.所以共享对象)。

关于c - Ubuntu C 程序可加载模块和 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21706421/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com