如何使用 dlmopen 在不同的线程中打开多个共享库?

Posted

技术标签:

【中文标题】如何使用 dlmopen 在不同的线程中打开多个共享库?【英文标题】:How to open many shared library in different thread using dlmopen? 【发布时间】:2019-01-22 16:00:50 【问题描述】:

我需要在不同线程中加载共享库所需的多次执行时间 (> 100000) 以进行并行执行。我无权访问这个共享库的源代码,它使用许多全局变量。这就是为什么我想加载 X 次这个共享库。

我尝试使用 dlmopen 执行此操作,但实际上从我的测试看来,同时限制在 15 个 dlmopen 左右。

void launch(int num) 
    void (*test)(int);
    char *error;

    void *handle = dlmopen(LM_ID_NEWLM, "/path/to/lib/libshared.so", RTLD_LAZY | RTLD_LOCAL);
    if (handle == NULL) 
        std::cout << "Load shared lib [FAILED] in thread: " << num << std::endl;
        return ;
    
    dlerror();
    *(void **) (&test) = dlsym(handle, "thread");
    if ((error = dlerror()) != NULL)  
        fprintf(stdin, "%s\n", error);
        exit(EXIT_FAILURE);
    
    (*test)(num);
    dlclose(handle);


int main(int ac, char **av) 
    try 
        std::vector<std::thread *> vec;
        for (int counter = 0; counter < 100; ++counter) 
            std::thread *t1 = new std::thread(launch, counter);
            vec.push_back(t1);
        

        for (std::vector< std::thread* >::iterator it = vec.begin() ; it != vec.end(); ++it) 
            (*it)->join();
            delete (*it);
        
        vec.clear();
     catch(std::exception const &e) 
        std::cerr << "[ERROR]: " << e.what() << std::endl;
        return(EXIT_FAILURE);
    
    return 0;

执行 15 个线程后对 dlmopen 的调用失败,您有什么想法或其他方法吗?

【问题讨论】:

不清楚为什么要多次加载而不是一开始就加载一次。 我要解决这个问题的方法是复制 .so 文件并在副本上使用 dlopen 这个库将它的上下文保存在内存中,我需要与我启动的线程一样多的上下文。 我想启动多个子进程会更好。 我无法提前知道我需要做多少 dlopen。 【参考方案1】:

经过研究,似乎在程序启动时,动态链接器会计算所有偏移量,并确保所有线程都有足够的空间容纳所有必需的线程局部变量。

使用 dlopen,这通常不起作用,因为无法移动线程控制块来为更多线程局部变量腾出空间。当前的 glibc 动态链接器为将来的 dlopen 调用保留了一些空间,但是如果您加载许多共享对象,每个共享对象都会枯萎自己的线程局部变量,这还不够。这就是为什么我得到“无法在静态 TLS 块中分配内存” .

glibc 实现最多支持 16 个命名空间。我必须找到其他解决方案。

【讨论】:

以上是关于如何使用 dlmopen 在不同的线程中打开多个共享库?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用CSV数据集配置在Jmeter的不同线程中使用不同输入登录多个用户

多线程基础知识了解一下

Windows线程同步详解

如何让一个类的多个实例(在不同的线程中)监听同一个事件?

微信小程序开发共工具怎么倒入源码

Android 线程间通信