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

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)使用 要动态加载此映像,当它加载时,会

一般来说,它对linux非常陌生,试图构建一个可加载的模块以供zabbix使用,这是可行的,但试图构建一个简单的shell程序来测试它。这意味着这个模块需要动态加载

可共享模块SNMPmath由以下内容构建:

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()
after
dlopen
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