shm_open 是共享库中未定义的符号

shm_open is an undefined symbol in shared library

我编译了一个目标文件shm.o并打包为共享库libshm.so

arm-linux-gnueabihf-gcc -fPIC -o shm.o -c shm.c
arm-linux-gnueabihf-gcc -shared shm.o -o libshm.so -lrt

其中 shm.cnm libshm.so 的输出如下所示。

/*shm.c*/

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

void func_shm(void)
{
    int ret = shm_open("/test_shm", O_CREAT, 0644);
}



/*output of nm*/

00000328 t $a
000002e4 t $a
00000484 t $a
...
...
00000328 t call_weak_fn
0001102c b completed.10740
         w __cxa_finalize@@GLIBC_2.4
...
...
0000034c t deregister_tm_clones
000003e0 t __do_global_dtors_aux
00010f0c t __do_global_dtors_aux_fini_array_entry
00011028 d __dso_handle
00010f10 a _DYNAMIC
00000484 t _fini
00000448 t frame_dummy
00010f08 t __frame_dummy_init_array_entry
00000498 r __FRAME_END__
0000044c T func_shm
00011000 a _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
000002e4 t _init
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
00000390 t register_tm_clones
         U shm_open@@GLIBC_2.4
0001102c d __TMC_END__

正如它所看到的,在倒数第二行,shm_open 是一个未定义的符号,即使附加了 -lrt

根据shm_open(3) — Linux manual page;但是,nm 中显示的 glibc 版本是 2.4。

These functions are provided in glibc 2.2 and later.

我的期望是

  1. libshm.so 将有一个定义 shm_open,因为-lrt被追加在命令的末尾;因此 shm_open 不会是一个未定义的符号。

  2. 任何调用 func_shm 的应用程序只需要 link libshm.so 未指定 -lrt

应该如何解决这个问题?

As it can see, at the second line to last, shm_open is a undefined symbol even though -lrt is appended.

这是预期:您link反对librt.soshm_open 定义 librt.so 中, 不在 中。

My expectation is that after linking process, libshm.so will have a definition of shm_open, so shm_open should not be an undefined symbol.

这个预期是错误的。

您所描述的是如果您link使用librt.a(存档库)编辑会发生什么。在那种情况下,linker 会将实现 shm_open() 的对象拉入 libshm.so.

但是由于您 link 反对 librt.so(它提供了定义),linker 只是记录 [=63= 需要 librt.so ] 时间,并且 shm_open() 需要在 运行 时间来自某个外部共享库。 libshm.so 中对 shm_open() 的引用仍未解决。

In addition, any application that invokes func_shm only needs to link to libshm.so without specifying -lrt

这是确实应该已经发生的事情(假设你linklibshm.so反对-lrt,就像你的命令行显示的那样)。

如果应用程序本身不从 librt.so 调用任何东西,而只调用 func_shm(),那么 link 使用 gcc main.o -L/... -lshm 应该可以工作。

我在 Linux/x86_64 上试过了,它成功了:

gcc -fPIC -shared -o libshm.so shm.c -lrt

# Verify that libshm.so requires librt.so:
readelf -d libshm.so | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]

gcc main.c -L. -lshm
# success

现在,您可能会感到困惑,因为按上面 link 编辑的应用程序实际上不会 运行:

./a.out
./a.out: error while loading shared libraries: libshm.so: cannot open shared object file: No such file or directory

但这是一个完全不同的问题——应用程序不知道要查找哪个目录libshm.so。要解决此问题,请添加 -Wl,-rpath=/path/to/dir(其中 /path/to/dir 是 运行 时要在其中找到 libshm.so 的目录)。