WSL 关闭/重新启动后,是什么导致共享对象依赖关系发生变化?

问题描述 投票:0回答:1

在 Ubuntu 22.04.3 WSL 实例中,我正在编译一个链接到

libuv
的共享库。

Ubuntu 22.04.3 WSL,直接来自 Microsoft Store,不包含

libuv
。通过
apt
包管理器安装它会在
/usr/lib/x86_64-linux-gnu/libuv.so
:

安装版本 1.43.0-1
$ find /usr -name libuv.so 2>/dev/null
$
$ sudo apt-get install -y libuv1-dev
# ...
$ find /usr -name libuv.so 2>/dev/null
/usr/lib/x86_64-linux-gnu/libuv.so
$
$ apt list | grep libuv1

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

libuv1-dev/jammy,now 1.43.0-1 amd64 [installed]
libuv1/jammy,now 1.43.0-1 amd64 [installed,automatic]
$

共享库的代码是一个较大项目的简化/MCVE。它需要版本 1.43.0-1 中不可用的

libuv
符号(特别是
uv_timespec64_t
和函数
uv_clock_gettime
)。因此,我安装了包含这些符号的较新版本。由于
apt
包管理器没有可用的新版本,因此我按照其 README.md 中的构建/安装说明进行操作。请注意,这似乎是在
/usr/local/lib/libuv.so
安装新版本,即它不会覆盖使用
apt-get
包管理器安装的版本:

$ git clone https://github.com/libuv/libuv.git && cd libuv && git checkout v1.45.0 && mkdir -p build && (cd build && cmake .. -DBUILD_TESTING=ON) && cmake --build build && (cd build && ctest -C Debug --output-on-failure) && sudo cmake --install build
# ...
$ 
$ find /usr -name libuv.so 2>/dev/null
/usr/lib/x86_64-linux-gnu/libuv.so
/usr/local/lib/libuv.so
$

现在,我的 Ubuntu WSL 实例中有两个版本的

libuv
:版本 1.43.0-1(位于
/usr/lib/x86_64-linux-gnu/libuv.so
)和版本 1.45.0(位于
/usr/local/lib/libuv.so
)。

这是我正在编译的共享库:

#include <uv.h>

int func() {
  uv_timespec64_t now;

  uv_close(NULL, NULL);
  uv_clock_gettime(UV_CLOCK_REALTIME, &now);

  return 0;
}

我编译如下:

$ cc --version && cc -fpic -ggdb -Wall -c -o func.o func.c
cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ cc -shared -o libfunc.so func.o  -fpic -ggdb -luv
$

ldd
报告的共享库依赖关系如下。请注意,它链接到版本 1.43.0-1,位于
/usr/lib/x86_64-linux-gnu/libuv.so
/lib
是到
/usr/lib
的符号链接):

$ ldd ./libfunc.so
        linux-vdso.so.1 (0x00007ffc74bdb000)
        libuv.so.1 => /lib/x86_64-linux-gnu/libuv.so.1 (0x00007f323f071000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f323ee49000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f323f0b1000)
$
$ ls -ld /lib
lrwxrwxrwx 1 root root 7 Nov 22 13:36 /lib -> usr/lib
$

但是,如果我关闭 (

wsl --shutdown
) 并重新启动我的 Ubuntu WSL 实例,那么无需(故意)更改环境或接触已编译的共享库,
ldd
现在报告它链接到版本 1.45.0,位于在
/usr/local/lib/libuv.so
:

$ # I've started this new Ubuntu WSL instance after shutting down the last instance with `wsl --shutdown`
$ 
$ ldd ./libfunc.so
        linux-vdso.so.1 (0x00007ffdd655d000)
        libuv.so.1 => /usr/local/lib/libuv.so.1 (0x00007fe8db267000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe8db03f000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe8db2b8000)
$

我的问题是:为什么“选择”链接的

libuv
在 WSL 实例关闭/重新启动后会发生变化?

这是 WSL 特定的吗?每个新实例都会在环境中调整某些内容(以及调整的“内容”是什么)?或者在物理关闭/重新启动后我会在任何 Linux PC 上观察到类似的行为吗?


如何打印ld(链接器)搜索路径,我知道如何查询链接器的有序搜索路径:

$ ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu")
SEARCH_DIR("=/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64")
SEARCH_DIR("=/usr/local/lib64")
SEARCH_DIR("=/lib64")
SEARCH_DIR("=/usr/lib64")
SEARCH_DIR("=/usr/local/lib")
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib")

...这意味着链接器更喜欢

/lib/x86_64-linux-gnu/libuv.so.1
(如前所述,链接到
/usr/lib/x86_64-linux-gnu/libuv.so.1
)而不是
/usr/local/lib/libuv.so.1
。这解释了
ldd
的关闭前输出,但没有解释
ldd
的重启后输出。


我知道的另一件可能相关的事情是

/etc/ld.so.conf
/etc/ld.so.conf.d/
。但是,关闭/重新启动 Ubuntu WSL 实例后,
/etc/ld.so.conf
/etc/ld.so.conf.d/
中的任何文件都没有更改。

c linker shared-libraries apt package-managers
1个回答
0
投票

由于 apt 包管理器没有可用的新版本,因此我按照 README.md 中的构建/安装说明进行操作。请注意,这似乎是在

/usr/local/lib/libuv.so
安装新版本。

这是一个非常糟糕的主意(TM)。

可以下载1.43源码包,查看配置情况;然后以同样的方式配置1.45。这应该会导致将二进制文件放入同一位置。然而,这也是一个坏主意,因为它会搞乱包管理器和依赖项,迟早会导致系统损坏。 更好的想法是配置非默认包并将其安装到非默认位置,例如

./configure --prefix /usr/local/libuv-1.45

该库将

不会

被随机构建使用;您必须专门指出它才能使用它。通常你会使用类似的东西: make LVTOP=/usr/local/libuv-1.45 CFLAGS='-I${LVTOP}/include' \ LDFLAGS='-L${LVTOP}/lib -rpath=${LVTOP}/lib'

指示编译器使用 
${LVTOP}/include

作为标头,链接器使用

${LVTOP}/lib
进行静态 (
ld
) 和动态 (
ld-linux.so
) 链接。

以这种方式使用时,额外的软件包不会以任何方式干扰系统,不会影响您的其他构建,并且不会在重新启动时神奇地更改配置。

附注这并没有直接回答“为什么重新启动会改变某些东西?”的问题,但请参阅上面的评论以了解我对为什么会发生这种情况的最佳猜测。

© www.soinside.com 2019 - 2024. All rights reserved.