动态链接的 glibc 应用程序 dlopen() 可以是静态链接的 musl 共享对象吗?

Can a dynamically linked glibc application dlopen() a static linked musl shared object?

我有一个当前针对 glibc 动态 link 编辑的库。 该库动态加载到应用程序中,该应用程序也针对 glibc 动态 linked。我无法控制应用程序,只能控制共享对象。

但是,有时加载库会导致应用程序获得 SIGKILLd,因为它具有非常严格的实时要求并且相应地设置了 rlimits。用分析器看这个告诉我大部分时间实际上花在 linker 上。所以本质上动态 linking 实际上太慢了(有时)。好吧,这不是我曾经想过的问题:)

我希望通过生成静态 linked 共享对象来解决这个问题。但是,谷歌搜索这个问题并阅读多个其他 SO 线程警告我不要尝试静态 link glibc。但这些似乎是 glibc 特定的问题。

所以我的问题是,如果我要针对 musl 静态 link 这个共享库,然后让一个(动态 linked)glibc 应用程序 dlopen 它,那会安全吗?多个 libc 是否存在一般问题?

Looking at this with a profiler tells me that most of the time is actually spent in the linker.

您的分析方法非常有问题。

首先,当应用程序 运行 时,“链接器”不会 运行,只有 loader(又名 rtld,又名 ld-linux) 做。我假设你的意思不是加载器,而不是链接器。

其次,加载器在启动时确实有一些运行时间成本,但是由于您调用的每个函数只被解析一次,加载程序的比例 运行 应用程序持续时间的时间成本 运行s 对于任何可观的时间(超过大约 1 分钟)应该很快接近零。

So essentially dynamic linking is actually too slow (sometimes).

您可以要求加载程序在加载时通​​过使用 -Wl,-z,now 链接器标志进行链接来解析共享库中的所有动态符号。

if I were to statically link this shared library against musl and then let a (dynamically linked) glibc application dlopen it, would that be safe?

这不仅不安全,而且很可能根本无法工作(大多数琐碎的共享库除外)。

Is there a problem in general with multiple libc's?

将多个 libc 链接到一个进程中会导致无法计数的问题。

更新:

resolving all symbols at load time is exactly the opposite of what I want, as the process gets sigkilled during loading of the shared object, after that it runs fine.

听起来您正在使用 dlopen 该进程 已经 执行时间关键的实时任务。

这不是明智之举:dlopen(除其他外)调用 malloc、从磁盘读取数据、执行 mmap 调用等 所有这些都需要锁,并且可以等待任意长的时间。

通常 解决方案是让应用程序执行初始化(加载您的库将是其中的一部分) 进入时间关键之前循环。

由于您无法控制应用程序,您唯一能做的就是告诉应用程序开发人员他们当前的要求(如果这些实际上是他们的要求)是不可满足的——他们必须提供一些方法来满足在进入时间关键部分之前执行初始化,否则他们将 总是SIGKILL 的风险。使您的库加载速度更快只会使 SIGKILL 出现的频率降低,但不会将其完全删除。

更新二:

yes, i'm aware that the best I can do is lower the frequency and not "solve" the problem, only try to mitigate it.

你应该调查一下 prelink。它可以大大减少执行重定位所需的时间。这不能保证您选择的预链接地址可用,因此您有时可能仍会收到 SIGKILLed,但这可能是一种有效的缓解措施。

理论上可以做类似的事情,但是你必须编写一个新版本的 musl 启动代码来处理线程指针和 TCB 已经由 glibc 设置的事实,并且 运行 该代码来自共享对象中的 ELF 构造函数。由于 TCB 布局差异,一些 musl 功能将不可用。

我认为这不太可能解决您的实际问题。即使它与时间相关,这个 hack 也可能使事情变得更糟,因为它 增加了 所需的 运行 时间重定位的数量。