Biblioteki współdzielone

Transkrypt

Biblioteki współdzielone
Projektowanie
oprogramowania
systemów
BIBLIOTEKI WSPÓŁDZIELONE
plan

biblioteki programistyczne

statyczne

współdzielone

łączenie dynamiczne

interfejs biblioteki

wtyczki programowe

kompatybilność wsteczna

„DLL hell”

przegląd użytecznych bibliotek
biblioteki programistyczne

biblioteka – kolekcja zasobów i procedur/funkcji używanych
przez programy komputerowe, posiadająca ściśle
zdefiniowany interfejs
 kod
dostarczany przez bibliotekę może być wykorzystany przez wiele
niepowiązanych programów – reużycie kodu
 program
nie musi znać implementacji funkcji bibliotecznych – polega
na ich interfejsie
 usługi
dostarczane w ramach biblioteki zwykle dotyczą wspólnego
zakresu zagadnień, dotyczą tego samego tematu (zestawu
tematów)
rodzaje bibliotek

biblioteki możemy podzielić ze względu na rodzaj łączenia (linking) - na
którym etapie tworzenia programu biblioteka jest łączona z programem
wykonywalnym

biblioteki statyczne (łączone statycznie) – stanowi kolekcję
skompilowanych plików obiektowych, które są wprost łączone do pliku
wykonywalnego podczas jego tworzenia, każdy plik wykonywalny
otrzymuje prywatną kopię kodu zawartego w bibliotece

biblioteki współdzielone (łączone dynamicznie) – kod biblioteki nie jest
kopiowany do pliku wykonywalnego, tylko dodawane są „łącza” do
biblioteki w osobnym pliku – ta sama biblioteka może być
współdzielona równocześnie przez wiele programów
porównanie bibliotek
statyczne
współdzielone

kopiowanie kodu

użycie współdzielonego kodu

zmiana biblioteki wymaga
rekompilacji/ponownego łączenia każdego
programu, który z niej korzysta

zmiana biblioteki możliwa poprzez zastąpienie
pliku biblioteki, o ile jest zachowany spójny
interfejs binarny i wsteczna kompatybilność

otrzymany program wykonywalny składa się
z pojedynczego pliku (łatwość dystrybucji)

program wykonywalny do działania wymaga
dodatkowych plików bibliotek

program wykonywalny nie wymaga łączenia  podczas uruchamiania programu następuje
bibliotek w czasie wykonania – brak
etap łączenia/relokacji bibliotek, który wiąże się
opóźnień przy starcie
z określonym kosztem czasu wykonania

program jest samowystarczalny (selfcontained)

poprawki w bibliotekach nie wymagają
instalowania nowych wersji programów, które z
nich korzystają

niższe użycie pamięci dyskowej (tylko 1 plik
biblioteki) i operacyjnej (obraz biblioteki jest
współdzielony pomiędzy procesami)
łączenie dynamiczne

w programie wykonywalnym zapisywana jest nazwa używanej biblioteki
współdzielonej oraz nazwy symboli eksportowanych przez bibliotekę lub
indeksy do tablicy symboli biblioteki

po uruchomieniu programu, używa on usługi linkera dynamicznego
dostarczanej przez OS, do

zlokalizowania biblioteki

załadowania jej obrazu do przestrzeni adresowej

wykonania niezbędnych relokacji symboli

umieszczenia referencji do symboli z biblioteki w odpowiednich slotach tablicy
symboli programu

uruchomienia kodu startowego biblioteki (np. DllMain(), dlinit(),
_declspec_(constructor))
ładowanie bibliotek w czasie
wykonania

łączenie dynamiczne nie musi odbywać się podczas startu programu
– możliwe jest w dowolnym momencie jego wykonania

ładowanie w czasie wykonania (run-time linking)

niejawne – następuje automatycznie podczas pierwszego odwołania do
jakiegokolwiek symbolu z biblioteki o opóźnionym czasie ładowania (lazy binding,
delay loading) – przyspiesza czas uruchomienia programu

jawne – kod programu w sposób jawny wywołuje funkcje służące do ładowania
biblioteki i uzyskania dostępu do symboli o określonej nazwie – biblioteka nie musi
być dostępna do uruchomienia programu – jej funkcjonalność może być
wykorzystana opcjonalnie – „wtyczki”
ładowanie bibliotek w czasie
wykonania
POSIX
Windows
ładowanie bibliotek w czasie
wykonania

typ symbolu (prototyp funkcji, jej sposób łączenia, typ parametrów
i wyniku) musi być znany a’priori – błędny typ spowoduje
zniszczenie stosu i crash programu

nazwa symbolu musi być znana a’priori – w przypadku C++ nazwa
dekorowana – nieprzenośne, dlatego stosujemy zwykle łączenie
typu „extern C”

symbol może odnosić się do eksportowanej funkcji lub zmiennej
globalnej
interfejs biblioteki

interfejs biblioteki to lista wszystkich eksportowanych symboli oraz ich typ

zwykle interfejs biblioteki jest dostarczany w postaci towarzyszących jej
plików nagłówkowych (.h), zawierających prototypy eksportowanych
funkcji/zmiennych globalnych

eksport symbolu z biblioteki

POSIX – domyślnie, wszystkie symbole zawarte w bibliotece są z niej eksportowane
(udostępniane klientom biblioteki) – przy dużych bibliotekach powoduje to znaczący
spadek wydajności

kompilatory zgodne z GCC udostępniają atrybut visibility określający czy symbol jest
eksportowany

Windows - kompilator Visual C++ udostępnia dyrektywy dllexport i dllimport dla
określenia symboli eksportowanych i importowanych z bibliotek
eksportowanie symbolu



na POSIX

kompilujemy całą bibliotekę z visibility=hidden (opcja -fvisibility=hidden)

używamy atrybutu visibility=„default” dla symboli, które chcemy eksportować
na Windows

dodajemy atrybut __declspec(dllexport) do symboli, które chcemy eksportować

w programie korzystającym z biblioteki używamy dla tych samych symboli
atrybutu __declspec(dllimport)
patrz przykład ->
eksportowanie
symboli
wtyczki programowe

„wtyczka” to specjalny rodzaj biblioteki współdzielonej, która jest
zaprojektowana, aby być ładowana w czasie działania programu

wtyczki udostępniają zunifikowany interfejs oparty o symbolach o
znanych nazwach i/lub klasach z „czysto wirtualnym” interfejsem

wymagana zgodność interfejsu binarnego pomiędzy wtyczkami

ukrywanie implementacji

obiekty „nieprzezroczyste” (opaque)

dostęp do stanu i zachowań obiektu tylko poprzez wywołania funkcji,
enkapsulacja danych

unikanie funkcji o dekorowanych nazwach (C++ name mangling) dla
zapewnienia przenośności dostępu do symboli
wtyczki programowe
wtyczki programowe i
kompatybilność wsteczna

gdyby implementacja klasy plugin_interface była jawna i użylibyśmy
funkcji nie-wirtualnych, wówczas jakakolwiek zmiana implementacji
powodowałaby, że dostęp do danych tej klasy wymagałby innego kodu
– zmiana interfejsu binarnego klasy

dla zapewnienia kompatybilności wstecznej, kolejne wersje klasy
plugin_interface muszą zachowywać dokładnie tą samą semantykę,
składnię (prototypy) oraz kolejność funkcji wirtualnych zdefiniowanych w
tablicy funkcji wirtualnych (vtable) poprzednich wersji klasy

kolejne wersje interfejsu plugin_interface powinny więc powstawać
poprzez dziedziczenie interfejsu z wersji wcześniejszej
kompatybilność wsteczna

typowe założenia wersjonowania bibliotek

kod korzystający z wcześniejszej wersji biblioteki powinien działać z nowszą
wersją biblioteki, o ile nie zmienił się główny numer wersji

zmiany „łamiące” kompatybilność (breaking changes) powinny wiązać się ze
zmianą głównego numeru wersji (major version number)

typowy format numerów wersji:
major_number.minor_number[.patch_number[.build_number]]

major_number – numer wersji interfejsu binarnego biblioteki, znaczna zmiana
funkcjonalności lub paradygmatu projektowania/użycia interfejsu

zmiana minor_number – rozszerzenia funkcjonalności nie łamiące
kompatybilności wstecznej

zmiana patch_number – poprawki błędów nie rozszerzające interfejsu biblioteki

build_number – numer kompilacji, używany np. do namierzenia, w którym dniu
pojawił się błąd w kodzie
„dll hell”

termin dll hell (piekło bibliotek łączonych dynamicznie) odnosi się do sytuacji, w której
w systemie istnieje kilka wersji tej samej biblioteki i nie jesteśmy w stanie określić, która z
nich jest ładowana przez nasz program wykonywalny – również niekompatybilne
wersje

generalnie występuje to tylko na Windows ze względu na kiepską implementację
mechanizmu linkera dynamicznego


linker dynamiczny sprawdza również katalog roboczy programu i wszystkie lokalizacje na
ścieżce systemowej (PATH)

brak ścisłego mechanizmu wersjonowania bibliotek

zdarzało się że program instalował wcześniejszą wersję biblioteki w katalogu systemowym
nadpisując wersję późniejszą i powodując niedziałanie wszystkich innych programów z niej
korzystających
nikłe szanse na POSIX

linker dynamiczny sprawdza tylko ściśle określone lokalizacje w poszukiwaniu bibliotek

mechanizm wersjonowania bibliotek umożliwiający precyzyjne określenie, która wersja
interfejsu jest niezbędna do działania (np. 2.X,1.3.X itp.)
przegląd użytecznych bibliotek
(C/C++)
C++ - Boost

zestaw bibliotek o bardzo szerokim zakresie tematycznym

gwarantują przenośne działanie na wielu platformach

zbudowane na bazie i rozszerzające bibliotekę standardową C++

jedne z najbardziej starannie zaprojektowanych i zaimplementowanych bibliotek dla
C++

biblioteki należące do Boost często stają się podstawą nowych specyfikacji w
rozwoju języka C++

ogółem kilkadziesiąt bibliotek dotyczących wszystkich możliwych aspektów
programowania

przystępując do rozwiązywania problemu zawsze warto sprawdzić, czy Boost już tego
nie robi

www.boost.org
Boost

Boost.Thread – przenośna implementacja wątków i obiektów
synchronizacji (stała się podstawą nagłówka <thread> C++11)

Boost.Atomic – implementacja atomowych zmiennych (podstawa dla
C++11 <atomic>)

Boost.Chrono, Boost.Date Time – pomiar czasu, formatowanie i
parsowanie dat i interwałów

Boost.Filesystem – przenośne operacje w systemie plików

Boost.Format – formatowanie napisów

Boost.Functional – programowanie funkcjonalne

Boost.Interprocess – obiekty IPC
Boost

Boost.Asio – przenośna biblioteka nieblokującej komunikacji sieciowej
i IPC

Boost.Lexical Cast – konwersja typów

Boost.Lockfree – kolejki nieblokujące

Boost.Log – logowanie błędów i wykonania programu

Boost.Math – funkcje matematyczne, m.in. interfejs C++ do biblioteki
BLAS (basic linear algebra subsystems)

Boost.Program Options – parsowanie plików konfiguracyjnych i
wiersza poleceń

Boost.Regex – wyrażenia regularne

Boost.Smart Ptr – „sprytne” wskaźniki zapobiegające wyciekom
pamięci
C++ - OpenCV

biblioteki algorytmów przetwarzania grafiki komputerowej, ale nie
tylko

przenośne działanie na wielu systemach

m.in. operacje matematyczne na macierzach wielowymiarowych

algorytmy mocno zoptymalizowane, korzystające z operacji
wektorowych procesorów

wsparcie dla obliczeń na GPU

kilkanaście różnych bibliotek do różnych celów

jedno z najpotężniejszych i najszerzej stosowanych narzędzi tego typu

„wrappery” do m.in. Javy, Pythona

www.opencv.org
OpenCV

core – operacje na macierzach, podstawowe typy graficzne,
rysowanie

imgproc – filtracja i transformacja obrazów, śledzenie obiektów

highgui – podstawowe elementy GUI

video – analiza ruchu, przepływ optyczny, usuwanie tła, filtracja
Kalmana

objdetect – wykrywanie obrazów

ml – uczenie maszynowe
portaudio

przenośna biblioteka (C) służąca do obsługi interfejsów
dźwiękowych

wsparcie m.in. dla API ASIO2 – niskie opóźnienia

zunifikowany interfejs na Windows, Mac OS X, Linux i wielu
innych systemach

www.portaudio.com
dsp++

biblioteka służąca do tworzenia algorytmów CPS w języku C++ z
wykorzystaniem programowania uogólnionego (szablonów)

m.in.

FFT (+ wrapper dla FFTW)

filtry cyfrowe FIR i IIR (projektowanie i uruchamianie)

korelacja

OLA, splot

przetwarzanie dźwięku – pomiar głośności (LUFS), procesory dynamiki

buforowanie, partycjonowanie, zakładkowanie

operacje stałopozycyjne

działa również na platformach mobilnych (Android NDK, iOS)

https://bitbucket.org/andrzejc/dsp
fftw

przenośna, zoptymalizowana biblioteka transformat FFT i innych

„fastest FFT in the west”

ciężki do ogarnięcia interfejs w C, ale olbrzymie możliwości

transformaty o rozmiarach pierwszysch

transformaty wielowymiarowe

DCT, MDCT, FHT

w C++ warto używać z wrapperem w dsp++

www.fftw.org
libsndfile

przenośna (C) biblioteka do odczytu i zapisu plików dźwiękowych w
różnych formatach

m.in. WAV, AIFF, FLAC…

również format MAT pochodzący z Matlaba – łatwe przenoszenie
danych podczas implementacji algorytmów prototypowanych w
Matlabie

w C++ warto używać wrappera w dsp++

http://www.mega-nerd.com/libsndfile/
Qt

przenośna biblioteka (C++) służąca do tworzenia GUI na wielu
platformach

zawiera również wiele innych funkcji poza GUI – komunikacja sieciowa,
multimedia

oryginalnie rozwijana przez Trolltech AG, potem Nokia – jest również
wersja OpenSource

zawiera język opisu UI QML i wsparcie dla JavaScript

prawdopodobnie najbardziej rozbudowane i najbardziej eleganckie UI
z wszystkich tego typu bibliotek

używa dodatkowego kompilatora metaobiektów – MOC –
skomplikowane użycie

wrapper dla Java

www.qt.io

Podobne dokumenty