用分析器查看这个告诉我,大部分时间实际上都花在了链接器上。
您的分析方法有很大问题。
首先,当应用程序运行时,“链接器”不会运行,只有加载器(又名 rtld,aka ld-linux
)会运行。我假设您的意思不是加载程序,而不是链接器。
其次,加载程序在启动时确实有一些运行时成本,但是由于您调用的每个函数只解析一次,因此在运行任何可感知时间(超过约 1 分钟)的应用程序期间,加载程序运行时成本的比例应该很快接近零。
所以本质上动态链接实际上太慢了(有时)。
您可以要求加载器在加载时通过链接-Wl,-z,now
器标志来解析共享库中的所有动态符号。
如果我将这个共享库与 musl 静态链接,然后让(动态链接的)glibc 应用程序 dlopen 它,那会安全吗?
这不仅不安全,而且很可能根本不起作用(大多数琐碎的共享库除外)。
多个libc一般有问题吗?
将多个 libc 链接到一个进程中会导致太多问题无法计算。
更新:
在加载时解析所有符号与我想要的完全相反,因为该进程在加载共享对象期间被终止,之后它运行正常。
听起来您正在使用进程已经在dlopen
执行时间关键的实时任务。
这不是明智的做法:(dlopen
除其他外)调用malloc
、从磁盘读取数据、执行mmap
调用等。所有这些都需要锁,并且可以等待任意长的时间。
通常的解决方案是让应用程序在进入时间关键循环之前执行初始化(加载您的库将是其中的一部分) 。
由于您无法控制应用程序,因此您唯一能做的就是告诉应用程序开发人员他们当前的需求(如果这些实际上是他们的需求)无法满足——他们必须在进入时间之前提供一些执行初始化的方法-关键部分,否则他们将始终冒SIGKILL
. 使您的库加载速度更快只会使它SIGKILL
以较低的频率出现,但不会完全删除它。
更新 2:
是的,我知道我能做的最好的事情就是降低频率而不是“解决”问题,只是试图减轻它。
您应该查看prelink。它可以显着降低执行重定位所需的时间。这不能保证您选择的预链接地址将可用,因此SIGKILL
有时您可能仍会收到 ed,但这可能是一种有效的缓解措施。