Próbuję załadować wspólną bibliotekę w C dwa razy:

lib1 = dlopen("mylib.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
lib2 = dlopen("mylib.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);

Chcę, aby lib1 i lib2 mają oddzielne przestrzenie adresowe, aby mogli zrobić różne rzeczy. Obecnie jedynym sposobem, w jaki mogę to osiągnąć, jest kopiowanie Mylib, aby kod wygląda na to:

lib1 = dlopen("mylib.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
lib2 = dlopen("mylib2.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);

W ograniczonym zakresie to dla mnie działa dobrze. Mam jednak aplikację, która wykorzystuje bibliotekę ogólną liczbę razy, co sprawia, że kopiowanie biblioteki uciążliwe.

Czy jest lepszy sposób na oddzielną przestrzeń adresową za każdym razem, gdy ładowana jest biblioteka?

EDYTOWAĆ:

Chcę załadować bibliotekę wielokrotnie, ponieważ moja aplikacja przetwarza rodzaj kolejki wiadomości. Elementy w kolejce wiadomości odnoszą się do nazwy biblioteki współdzielonej (np. Mylib) i zawierają zestaw danych, które są przetwarzane przez bibliotekę. Chcę przetworzyć MQ w środowisku wielokrotnym, uruchomieniu każdego połączenia do metody biblioteki we własnym wątku. Dopóki MQ zawiera połączenie do biblioteki tylko raz, wszystko działa zgodnie z oczekiwaniami. Jednak gdy mam dwa przedmioty, które korzystają z tej samej biblioteki, zaczynają się dziwnie.

2
MiH 19 luty 2018, 13:59

3 odpowiedzi

Najlepsza odpowiedź

Nie jestem pewien, dlaczego to pytanie zostało obniżone, jest idealnie rozsądne.

Musisz użyć Dlmopen, aby osiągnąć ten rodzaj izolacji:

// No need for RTLD_LOCAL, not sure about RTLD_DEEPBIND
lib1 = dlmopen (LM_ID_NEWLM, "mylib.so", RTLD_LAZY | RTLD_DEEPBIND);
6
yugr 20 luty 2018, 15:23

Cała idea dynamicznie ładowania kodu jest to, że jesteś w stanie go udostępnić, w szczególności z innymi procesami. Z tego powodu nie sądzę, że możliwe jest dwukrotnie ładowanie biblioteki.

Na tym są sposoby. Można oszukać dynamicznego łącznika do ładowania go po raz drugi. Kopiowanie biblioteki jest jednym ze sposobów, w jaki już znalazłeś. Mogę sobie wyobrazić ciężkie linki do pracy.

Myślę jednak, że byłoby lepiej, gdybyś pracował z przepływem tutaj. Widzę dwa sposoby osiągnięcia tego, co myślę, że jest Twoim celem: rozwidlając oddzielny proces lub tworzenie oddzielnej funkcji init.

W przypadku oddzielnego procesu, po prostu fork(), po utworzeniu odpowiednich mechanizmów IPC między rodzicem a dzieckiem, zamiast ładować bibliotekę po raz drugi. Ponieważ widelec tworzy nowy proces, otrzymuje własną przestrzeń pamięci i rzeczy pozostają oddzielne. Jako IPC, sugerowałem użycie jakiegoś oprogramowania pośredniego, takiego jak Zeromq, DBUS lub XMLRPC.

Tworzenie oddzielnej funkcji init jest inna opcja. W tym celu, zamiast tworzyć stan biblioteki jako global, rzucasz je razem w strukturę. Następnie, w tej funkcji init, tworzysz instancję tej struktury, ustaw go i zwraca swój adres. Wszystkie inne funkcje, które wcześniej obsługiwane w stanie globalnym, teraz otrzymują adres tej struktury jako dodatkowy (zwyczajowy pierwszy) parametr. Zamiast ładować bibliotekę dwukrotnie, możesz dwukrotnie wywołać funkcję init, aby skonfigurować oddzielne otoczenie.

3
Ulrich Eckhardt 19 luty 2018, 11:14

Czy jest lepszy sposób na oddzielną przestrzeń adresową za każdym razem, gdy ładowana jest biblioteka?

Właściwie, a Wirtualna przestrzeń adresowa należy do Proces (więc do wszystkich wątków wewnątrz IT), nie do biblioteki współdzielonej (która używa kilka segmentów tej przestrzeni wirtualnej adresu).

Dla procesu PID 1234, użyj PMAP (1) (jak pmap 1234) lub Proc (5) (np. spróbuj cat /proc/1234/maps ...)

Naprawdę powinieneś unikać Dlopen (3) - ing to samo dzielona biblioteka "dwukrotnie" (i jest to trudne, celowo; możesz użyć symboli i dlopen kilku symetrów do tego samego obiektu współdzielonego, ale Nie powinno być , na przykład, ponieważ dane static byłyby "załadowane dwukrotnie", a następstwa nastąpi). Aby tego uniknąć, Dynamic Loader używa Odliczanie referencyjne techniki ...

Przeczytaj również DRPPER'S Jak pisać biblioteki współdzielone

Czy jest lepszy sposób na oddzielną przestrzeń adresową za każdym razem, gdy ładowana jest biblioteka?

Potrzebujesz wtedy różnych procesów , każdy posiadający własną wirtualną przestrzeń adresową. Użyjesz Inter-Proces Komunikacja : patrz < href = "http://man7.org/linux/man-pages/man7/pipe.7.html" rel = "NOFollow NorefErr"> Rura (7) FIFO (7), Gniazdo (7), UNIX (7), shm_overview (7), SEM_OOVERVIEW ( 7) itp. ...

-1
Basile Starynkevitch 19 luty 2018, 11:26