2009-11-17 30 views
12

Sono in esecuzione su Linux e mi piacerebbe essere in grado di effettuare chiamate di funzioni parallele in una libreria condivisa (.so) che sfortunatamente non è protetta da thread (credo che abbia delle strutture dati globali).Carica più copie di una libreria condivisa

Per motivi di prestazioni, non voglio semplicemente racchiudere le chiamate di funzione in un mutex.

Quello che mi piacerebbe fare è generare, diciamo 4 thread, e anche caricare 4 copie della stessa libreria nella memoria del processo. Ciascun thread quindi effettua le chiamate di funzione nella propria copia della libreria.

Sfortunatamente, dlopen non mi consente di caricare più istanze di qualsiasi libreria.

Qualcuno conosce qualche metodo che mi consenta di caricare la libreria più di una volta? (Oltre a creare 4 copie del file .so, ognuna con un nome diverso)

+0

Per coloro che hanno bisogno di un esempio, implementato il confronto [qui] (https://github.com/ikoryakovskiy/not_threadsafe_test). – Ivan

risposta

6

Invece di utilizzare i thread, è possibile utilizzare più processi, ognuno dei quali esegue parte del lavoro. Questo è molto comune su * nix e di solito è più facile da codificare.

+2

Non so più facile da codificare. Certo, è leggermente più facile chiamare 'fork()', allora è per lanciare un thread. Ma se hai bisogno di comunicare tra processi o condividere dati tra processi, allora entri nel mondo di IPC, (memoria condivisa, pipe, ecc.), Che è indubbiamente più complicato da codificare. –

+2

Per i principianti, è più facile usare la sua libreria non thread-safe. :) Trovo più facile codificare perché è più facile evitare deadlock e problemi correlati, ma, sì, hanno anche le loro versioni in IPC. –

+1

@Charles - dato l'obiettivo dell'OP, passare a più processi è probabilmente la sua opzione meno dolorosa. –

1

Sembra una cattiva idea. Ciò non è più possibile con le librerie condivise come sarebbe con quelle statiche.

Probabilmente potresti usare dlopen() con il flag RTLD_LOCAL in modo che le chiamate successive a dlopen non vedano che è già caricato e lo fanno funzionare come vuoi ... ma sembra ancora una cattiva idea di design. Se si verificano problemi di prestazioni, sarebbe meglio evitare di ingombrare la memoria con diverse copie della stessa libreria.

Vorrei suggerire l'utilizzo di diversi processi o il modo mutex, è probabilmente più efficiente.

Mentre lavori su Linux, potrebbero esistere altri approcci se puoi accedere al codice sorgente della libreria, come rinominare i suoi simboli in modo da avere tutte le istanze separate necessarie ... Bene, una volta ottenuta la fonte, potrebbe altri modi, come rendere sicuro il thread della libreria.

0

Che libreria è? È qualcosa di grande? Mi chiedo se non è possibile correggere la libreria in qualche modo in modo sicuro, quindi creare il codice utilizzando la versione protetta da file della libreria. Dipende dalla dimensione della libreria, e cosa c'è di sbagliato in essa, ma se tu potessi aggiustare la libreria, saresti in grado di costruire la tua app nel modo che desideri, così come aiutare tutti gli altri.

+1

Perché stai formulando la frase come l'esposizione di un'API non protetta da un errore è qualcosa di sbagliato e richiede una correzione? Ci sono dei compromessi sia a fornire garanzie sulla sicurezza del filo, sia no. – ulidtko

+0

@ulidtko - la domanda originale riguarda l'utilizzo di un'API non protetta da un thread in un modo in cui la mancanza di sicurezza del thread interromperà le cose. Per gli scopi del poster originale, la libreria IS è rotta. Ovviamente non ci sono problemi con le API non thread-safe, ma per l'OP, le correzioni devono essere fatte prima che la libreria sia utilizzabile. È una cosa di contesto. –

+0

@ulidtko - Inoltre, non sappiamo perché la libreria non sia protetta da thread. Esistono molte buone ragioni per cui il codice non è protetto da un thread (ad esempio, i contenitori STL non sono thread-safe), ma ci sono anche molti buoni motivi (ad esempio, il vecchio C strtok usa un puntatore statico interno, che forse aveva senso al momento, ma sembra piuttosto stupido dal punto di vista di oggi). –

7

È possibile carico copie multiple indipendenti della libreria in questo modo:

#define _GNU_SOURCE 
#include <dlfcn.h> 
... 
void *handle = dlmopen(LM_ID_NEWLM, "/path/to/library.so", RTLD_NOW); 

Maggiori informazioni here.

+0

Qualche idea su noi utenti poveri di Windows? Questo è molto utile per Linux però. – ibell

+0

Funziona anche in Windows con LoadLibrary e GetProcAddress. Penso che sia necessario disporre di più copie fisiche della DLL, ma funziona correttamente. –

+0

Grazie! Questo ti permette di fare qualcosa di pazzo come avvolgere una libreria C senza thread-safe in una classe C++. L'operatore new() della classe carica la libreria con LM_ID_NEWLM quindi usa dlsym() per popolare i puntatori di funzione della libreria come campi nella classe. Usa come una classe C++ come faresti normalmente. Un po 'un trucco malvagio, ma funziona quando non si vogliono refactoring 10.000 linee di codice da qualcuno che appartiene nelle profondità dell'inferno per l'utilizzo di stato condiviso statico. – AdamIerymenko

Problemi correlati