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.c
和 nm 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.
我的期望是
libshm.so
将有一个定义
shm_open
,因为-lrt
被追加在命令的末尾;因此 shm_open
不会是一个未定义的符号。
任何调用 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.so
。 shm_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
的目录)。
我编译了一个目标文件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.c
和 nm 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.
我的期望是
libshm.so
将有一个定义shm_open
,因为-lrt
被追加在命令的末尾;因此shm_open
不会是一个未定义的符号。任何调用
func_shm
的应用程序只需要 linklibshm.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.so
。 shm_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
的目录)。