简体   繁体   English

如何链接非线程安全库,以便每个线程都有自己的全局变量?

[英]How to link non thread-safe library so each thread will have its own global variables from it?

I have a program that I link with many libraries. 我有一个程序,我链接到许多库。 I run my application on profiler and found out that most of the time is spent in "waiting" state after some network requests. 我在profiler上运行我的应用程序,发现在一些网络请求之后大部分时间都花在“等待”状态。 Those requests are effect of my code calling sleeping_function() from external library. 这些请求是我的代码从外部库调用sleeping_function()效果。 I call this function in a loop which executes many, many times so all waiting times sum up to huge amounts. 我在循环中调用此函数,该循环执行许多次,因此所有等待时间总计达到大量。

As I cannot modify the sleeping_function() I want to start a few threads to run a few iterations of my loop in parallel. 由于我无法修改sleeping_function()我想启动一些线程并行地运行我的循环的几次迭代。 The problem is that this function internally uses some global variables. 问题是这个函数在内部使用了一些全局变量。

Is there a way to tell linker on SunOS that I want to link specific libraries in a way that will place all variables from them in Thread Local Storage? 有没有办法告诉SunOS上的链接器我想以某种方式链接特定的库,将所有变量放在线程本地存储中?

I don't think you'll be able to achieve this with just the linker, but you might be able to get something working with some code in C. 我不认为你只能使用链接器来实现这一点,但是你可能能够在C中使用某些代码。

The problem is that a call to load a library that is already loaded will return a reference to the already loaded instance instead of loading a new copy. 问题是加载已加载库的调用将返回对已加载实例的引用,而不是加载新副本。 A quick look at the documentation for dlopen and LoadLibrary seems to confirm that there's no way to load the same library more than once, at least not if you want the image to be prepared for execution. 快速查看dlopenLoadLibrary的文档似乎确认无法多次加载同一个库,至少在您希望图像准备好执行时是这样。 One way to circumvent this would be to prevent the OS from knowing that it is the same library. 避免这种情况的一种方法是阻止操作系统知道它是同一个库。 To do this you could make a copy of the file. 为此,您可以复制该文件。

Some pseudo code, just replace calls to sleeping_function with calls to call_sleeping_function_thread_safe : 一些伪代码,只需通过调用call_sleeping_function_thread_safe来替换对sleeping_function的调用:

char *shared_lib_name

void sleeping_function_thread_init(char *lib_name);

void call_sleeping_function_thread_safe()
{
  void *lib_handle;
  pthread_t pthread;
  new_file_name = make_copy_of_file(shared_lib_name);

  pthread_create(&pthread, NULL, sleeping_function_thread_init, new_file_name);
}

void sleeping_function_thread_init(char *lib_name)
{
  void *lib_handle;
  void (*)() sleeping_function;

  lib_handle = dlopen(lib_name, RTLD_LOCAL);
  sleeping_function = dlsym(lib_handle, "sleeping_function")
  while (...)
    sleeping_function;
  dlclose(lib_handle);
  delete_file(lib_name);      
}

For windows dlopen becomes LoadLibrary and dlsym becomes GetProcAddress etc... but the basic idea would still work. 对于Windows, dlopen变为LoadLibrarydlsym变为GetProcAddress等......但基本思想仍然可行。

In general, this is a bad idea. 一般来说,这是一个坏主意。 Global data isn't the only issue that may prevent a non thread-safe library from running in a multithreaded environment. 全局数据不是唯一可能阻止非线程安全库在多线程环境中运行的问题。

As one example, what if the library had a global variable that points to a memory-mapped file that it always maps into a single, hardcoded address. 作为一个示例,如果库具有指向内存映射文件的全局变量,它总是映射到单个硬编码地址。 In this case, with your technique, you would have one global variable per thread, but they would all point to the same memory location, which would be trashed by multi-threaded access. 在这种情况下,使用您的技术,每个线程将有一个全局变量,但它们都指向相同的内存位置,这将被多线程访问所破坏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM