为什么具有线程本地存储的库的 shl_load() 会失败?
默认情况下,Perl 中的线程为所有变量采用自己的本地存储,以最大限度地减少线程对现有非线程感知代码的影响。 在 Perl 中,可以使用以下属性创建线程共享变量:
use threads;
use threads::shared;
my $localvar;
my $sharedvar :shared;
HP-UX 运行时加载程序不支持动态加载包含 (TLS) 线程本地存储的共享库。
因此,当尝试导入包含 TLS 的模块时,会报告以下错误:
"/usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage"
所以我知道为什么会收到错误,只是不清楚为什么使用 TLS 加载库会很困难?
Threads in Perl by default take their own local storage for all variables, to minimise the impact of threads on existing non-thread-aware code. In Perl, a thread-shared variable can be created using an attribute:
use threads;
use threads::shared;
my $localvar;
my $sharedvar :shared;
HP-UX runtime loader does not support dynamic load of shared libraries that contain (TLS) thread local storage.
As a result, when attempting to import modules that contain TLS the following error is reported:
"/usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage"
So I know why I am getting an error I am just unclear as to why it would be difficult to load a library with TLS?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
TLS 存储的设置方式取决于 TLS 访问
在更简单的“初始可执行文件/静态 TLS”模型中,加载程序在运行主可执行文件的第一条指令之前设置 TLS 段。 它通过将主可执行文件及其直接依赖的所有共享库的 TLS 要求相加来计算该段的大小。
一旦分配并设置了该 TLS 段,应用程序就开始运行,并且可以将指针存储到 TLS 段中。 因此,不可能对段进行 realloc() 存储——加载程序不知道应用程序中的哪些指针必须更新。
由于您无法重新分配该段,并且其中没有空间用于其他变量; 加载器如何处理需要自己的 TLS 存储的动态加载库?
glibc 加载器实际上在初始 TLS 中分配了一些额外的空间,因此它可以使用 TLS 动态加载库,只要它们不使用太多空间。 一旦此保留用尽,glibc 加载器也将拒绝加载任何具有 TLS 要求的其他库。
在 Solaris 和 Linux 上,可以使用“常规动态 TLS 模型"。
看起来 HP-UX v1.6 也支持该模型,事实上,它已成为默认值。 但您可能正在运行较旧的操作系统版本,该模型不是默认模型,并且可能根本不受支持。 检查您的编译器版本是否支持
+tls=dynamic
选项,如果支持,使用它进行构建是否有帮助。The way TLS storage is set up depends on the TLS access model.
In the simpler "Initial executable / static TLS" model, the loader sets up TLS segment before the first instruction of the main executable is run. It computes the size of that segment by adding up TLS requirements of the main executable and all shared libraries it directly depends on.
Once this TLS segment is allocated and set up, the application starts running, and may well store pointers into the TLS segment. Hence it's impossible to
realloc()
storage for the segment -- the loader would have no idea which pointers in the application must be updated.Since you can't realloc the segment, and since there is no space in it for additional variables; how can loader deal with dynamically loaded libraries which require TLS storage of their own?
The glibc loader actually allocates some extra space in the initial TLS, and so it can dynamically load libraries with TLS, provided they don't use too much space. Once this reserve is exhausted, glibc loader will also refuse to load any additional libraries with TLS requirements.
On Solaris and Linux it is possible to dynamically load libraries with arbitrary TLS requirements, using the "General Dynamic TLS model".
It looks like HP-UX v1.6 also supports that model, and in fact makes it the default. But you are probably running an older OS release, where this model is not the default, and may not be supported at all. Check if your compiler version supports
+tls=dynamic
option, and if so whether building with it helps.