Ubuntu C程序可加载模块和未定义符号

时间:2014-02-11 15:45:51

标签: c linux

一般来说对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文件似乎有效。

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

聚苯乙烯。关闭在第一个提议的答案中阅读论文。

1 个答案:

答案 0 :(得分:2)

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

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

(另见this answer

您可能希望将-lsomething(我不知道哪些,您可能知道!)这些库添加到正在构建gcc -shared的命令SNMPmath.so中....您不希望将libsnmp.a之类的静态库链接到它(您应该将共享库链接到SNMPmath.so共享对象)。