2010-09-15 59 views
4

我有一個程序,我與許多圖書館鏈接。我在探查器上運行我的應用程序,發現大部分時間都是在一些網絡請求後用於「等待」狀態。 這些請求是我的代碼從外部庫調用sleeping_function()的影響。 我在一個執行許多次循環的循環中調用這個函數,這樣所有的等待時間總計爲大量。如何鏈接非線程安全的庫,以便每個線程都有它自己的全局變量?

因爲我不能修改sleeping_function()我想開始幾個線程來並行運行我的循環的幾個迭代。問題是這個函數在內部使用了一些全局變量。

有沒有辦法告訴SunOS上的鏈接器,我想以某種方式鏈接特定的庫,將所有變量從它們放置在線程本地存儲中?

+1

不錯的問題。請Linux/Windows解決方案也。 – 2010-09-15 13:22:54

回答

0

我不認爲你就可以只用連接器來實​​現這一點,但你也許能夠得到的東西與一些代碼工作中C.

的問題是,調用加載已加載的庫將返回對已加載實例的引用,而不是加載新副本。快速瀏覽dlopenLoadLibrary的文檔似乎證實,無法多次加載相同的庫,至少在您希望圖像準備好執行時無法加載。避免這種情況的一種方法是防止操作系統知道它是同一個庫。要做到這一點,你可以製作一份文件的副本。

一些僞代碼,只需用電話代替調用sleeping_functioncall_sleeping_function_thread_safe

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);  
} 

對於windows dlopen變得LoadLibrarydlsym成爲GetProcAddress等...但其基本思想仍然能工作。

+0

這將不起作用,因爲我必須靜態鏈接整個程序。 – elmo 2010-09-15 14:15:16

1

一般來說,這是一個壞主意。全局數據不是唯一可能阻止非線程安全庫在多線程環境中運行的問題。

作爲一個例子,如果庫有一個全局變量指向一個內存映射文件,它總是映射到一個單一的硬編碼地址。在這種情況下,使用您的技術,每個線程都會有一個全局變量,但它們都指向相同的內存位置,這將會被多線程訪問所破壞。

+0

我同意,但事實並非如此。我有權訪問庫的來源,但我無法更改任何內容,而必須鏈接到給定的靜態庫對象。 – elmo 2010-09-15 14:24:18

+0

這就是一個例子。你確定圖書館沒有假設它是在一個單獨的線程中運行嗎?甚至沒有隱含的假設? – 2010-09-15 16:38:28