共享库(dlopen)和库静态指针的线程安全性

时间:2012-03-02 14:11:50

标签: linux shared-libraries

当我动态加载共享库时,例如在Linux上使用dlopen,我是否必须担心处理器之间加载库的可见性,还是会自动隔离/确保安全?

例如,假设我在加载的库中有这个函数:

char const * get_string()
{  return "literal"; }

在主程序中使用这样的字符串文字指针在多个线程之间是安全的,因为它们都保证看到它的初始值。但是,我想知道“初始值”的规则如何真正适用于加载的库(因为标准对它没有多大帮助。

假设我加载了库,然后立即调用get_string函数。我通过非内存序列原子将指针传递给另一个线程(在C ++ 11用法中放松)。另一个线程可以安全地使用此指针,而不必发出任何加载围栏或其他同步指令吗?

我的假设是它是安全的。也许是因为新库将被加载到新页面中,其他核心还无法加载它们,因此无法对它们进行旧的可见性?

如果可能的话,我希望某种授权参考作为答案的一部分。或者默认情况下如何使其成为线程安全的技术说明。或者当然是反驳,如果它本身不是线程安全的。

2 个答案:

答案 0 :(得分:1)

您的问题是:dlopen()在返回之前是否会正确加载我的所有lib代码?是的,它会的。 否则你只有一个线程会遇到问题。如果你必须在dlopen异步完成之前睡觉,那将很难处理。它还将执行各种检查并初始化需要之前您有机会获得所需的函数指针。这意味着如果你得到那个指针,一切都在这里,你可以直接在任何线程中使用。

当然,你需要用通常的线程安全传递那个指针,但我想你知道怎么做。

请注意静态初始化和模块不能很好地协同工作(请参阅关于该主题的所有其他问题)。

您对核心的评论很奇怪。核心不加载内存。他们在缓存中预取它,但这不是问题,只是有点慢。

答案 1 :(得分:1)

我将扩展Basile所说的内容。我跟着glibc跟进,发现dlopen在deed中使用了mmap。所有内存可见性保证均来自mmap系统调用,dlopen本身不做任何额外保证。

mmap的用户通常认为它会在返回时在所有处理器上正确映射内存,这样就不会考虑可见性。这似乎并不是一个明确的保证,但如果没有这样的保证,操作系统可能无法使用。还没有已知的系统,这不能按预期工作。