为什么对于具有线程本地存储的库,shl_load()会失败?

时间:2022-09-01 09:29:38

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:

默认情况下,Perl中的线程为所有变量使用自己的本地存储,以最小化线程对现有非线程感知代码的影响。在Perl中,可以使用属性创建线程共享变量:

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:

HP-UX运行时加载程序不支持动态加载包含(TLS)线程本地存储的共享库。因此,在尝试导入包含TLS的模块时,会报告以下错误:

"/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?

所以我知道为什么我会收到错误我不清楚为什么用TLS加载库会很困难?

1 个解决方案

#1


The way TLS storage is set up depends on the TLS access model.

TLS存储的设置方式取决于TLS访问模型。

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.

在更简单的“初始可执行/静态TLS”模型中,加载程序在运行主可执行文件的第一条指令之前设置TLS段。它通过添加主可执行文件的TLS要求以及它直接依赖的所有共享库来计算该段的大小。

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.

一旦分配并设置了此TLS段,应用程序就会开始运行,并且可能会将指针存储到TLS段中。因此,不可能为段重新存储()存储 - 加载器不知道必须更新应用程序中的哪些指针。

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?

由于您无法重新分配该段,并且因为其中没有空间用于其他变量;装载程序如何处理动态加载的库,这些库需要自己的TLS存储?

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.

glibc加载器实际上在初始TLS中分配了一些额外的空间,因此它可以使用TLS动态加载库,只要它们不占用太多空间。一旦此保留用尽,glibc加载程序也将拒绝加载任何具有TLS要求的其他库。

On Solaris and Linux it is possible to dynamically load libraries with arbitrary TLS requirements, using the "General Dynamic TLS model".

在Solaris和Linux上,可以使用“常规动态TLS模型”动态加载具有任意TLS要求的库。

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.

看起来HP-UX v1.6也支持该模型,实际上它是默认的。但是您可能正在运行较旧的操作系统版本,此版本不是默认版本,可能根本不受支持。检查您的编译器版本是否支持+ tls = dynamic选项,如果是,则使用它构建是否有帮助。

#1


The way TLS storage is set up depends on the TLS access model.

TLS存储的设置方式取决于TLS访问模型。

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.

在更简单的“初始可执行/静态TLS”模型中,加载程序在运行主可执行文件的第一条指令之前设置TLS段。它通过添加主可执行文件的TLS要求以及它直接依赖的所有共享库来计算该段的大小。

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.

一旦分配并设置了此TLS段,应用程序就会开始运行,并且可能会将指针存储到TLS段中。因此,不可能为段重新存储()存储 - 加载器不知道必须更新应用程序中的哪些指针。

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?

由于您无法重新分配该段,并且因为其中没有空间用于其他变量;装载程序如何处理动态加载的库,这些库需要自己的TLS存储?

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.

glibc加载器实际上在初始TLS中分配了一些额外的空间,因此它可以使用TLS动态加载库,只要它们不占用太多空间。一旦此保留用尽,glibc加载程序也将拒绝加载任何具有TLS要求的其他库。

On Solaris and Linux it is possible to dynamically load libraries with arbitrary TLS requirements, using the "General Dynamic TLS model".

在Solaris和Linux上,可以使用“常规动态TLS模型”动态加载具有任意TLS要求的库。

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.

看起来HP-UX v1.6也支持该模型,实际上它是默认的。但是您可能正在运行较旧的操作系统版本,此版本不是默认版本,可能根本不受支持。检查您的编译器版本是否支持+ tls = dynamic选项,如果是,则使用它构建是否有帮助。