biblioteki współdzielone

28
Projektowanie oprogramowania systemów BIBLIOTEKI WSPÓŁDZIELONE

Upload: duongbao

Post on 11-Jan-2017

231 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Biblioteki współdzielone

Projektowanie

oprogramowania

systemów BIBLIOTEKI WSPÓŁDZIELONE

Page 2: Biblioteki współdzielone

plan

biblioteki programistyczne

statyczne

współdzielone

łączenie dynamiczne

interfejs biblioteki

wtyczki programowe

kompatybilność wsteczna

„DLL hell”

przegląd użytecznych bibliotek

Page 3: Biblioteki współdzielone

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)

Page 4: Biblioteki współdzielone

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

Page 5: Biblioteki współdzielone

porównanie bibliotek

statyczne

kopiowanie kodu

zmiana biblioteki wymaga

rekompilacji/ponownego łączenia każdego

programu, który z niej korzysta

otrzymany program wykonywalny składa się

z pojedynczego pliku (łatwość dystrybucji)

program wykonywalny nie wymaga łączenia

bibliotek w czasie wykonania – brak

opóźnień przy starcie

program jest samowystarczalny (self-

contained)

współdzielone

użycie współdzielonego kodu

zmiana biblioteki możliwa poprzez zastąpienie

pliku biblioteki, o ile jest zachowany spójny

interfejs binarny i wsteczna kompatybilność

program wykonywalny do działania wymaga

dodatkowych plików bibliotek

podczas uruchamiania programu następuje

etap łączenia/relokacji bibliotek, który wiąże się

z określonym kosztem czasu wykonania

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)

Page 6: Biblioteki współdzielone

łą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))

Page 7: Biblioteki współdzielone

ł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”

Page 8: Biblioteki współdzielone

ładowanie bibliotek w czasie

wykonania

POSIX Windows

Page 9: Biblioteki współdzielone

ł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

Page 10: Biblioteki współdzielone

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

Page 11: Biblioteki współdzielone

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 ->

Page 12: Biblioteki współdzielone

eksportowanie

symboli

Page 13: Biblioteki współdzielone

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

Page 14: Biblioteki współdzielone

wtyczki programowe

Page 15: Biblioteki współdzielone

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

Page 16: Biblioteki współdzielone

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

Page 17: Biblioteki współdzielone

„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.)

Page 18: Biblioteki współdzielone

przegląd użytecznych bibliotek

(C/C++)

Page 19: Biblioteki współdzielone

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

Page 20: Biblioteki współdzielone

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

Page 21: Biblioteki współdzielone

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

wiele wiele innych…

Page 22: Biblioteki współdzielone

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

Page 23: Biblioteki współdzielone

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

Page 24: Biblioteki współdzielone

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

Page 25: Biblioteki współdzielone

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

Page 26: Biblioteki współdzielone

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

Page 27: Biblioteki współdzielone

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/

Page 28: Biblioteki współdzielone

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