Remove ads
Sammlung von Unterprogrammen/-Routinen Aus Wikipedia, der freien Enzyklopädie
Eine Programmbibliothek (kurz Bibliothek; englisch library, kurz lib) bezeichnet in der Programmierung eine Sammlung von Unterprogrammen/-routinen, die Lösungswege für thematisch zusammengehörende Problemstellungen anbieten. Bibliotheken sind im Unterschied zu Programmen keine eigenständig lauffähigen Einheiten, sondern sie enthalten Hilfsmodule, die von Programmen angefordert werden.
In erweitertem Sinn gelten als Programmbibliotheken (zum Teil auch „Komponentenbibliothek“ oder „Klassenbibliothek“ genannt) alle Arten von Bibliotheken, die Programmcode(-bestandteile) bereitstellen/enthalten. Insofern unterscheidet man Programmbibliotheken u. a. nach dem Typ des Programmcodes, z. B. Quelltexte, Makros, Object- oder Bytecode, Maschinencode usw. Dementsprechend werden Bibliotheken zu unterschiedlichen Zeitpunkten benutzt, manche nur im Rahmen der Softwareentwicklung (von Werkzeugen der Entwicklungsumgebung), andere nur zur Ausführung von Programmen, wieder andere als Mischform von beiden. Solche Bibliotheken enthalten häufig nicht nur Unterprogramme, sondern Programmcodeteile aller Programm-Typen.
Eine besondere Form von Programmbibliotheken sind Frameworks.
Mögliche Zugriffe auf Funktionen einer Programmbibliothek sind durch die Programmierschnittstelle (API) definiert. Dabei handelt es sich um die Gesamtheit der öffentlich verfügbaren Funktionen und Klassen; in Abgrenzung zu den privaten Einheiten der Bibliothek, die nicht zugänglich sind.
Manche proprietären Programmbibliotheken werden nicht im Quelltext veröffentlicht, da sie Firmengeheimnisse darstellen. Zum Schutz gegen Dekompilieren wird dann oft ein Obfuscator eingesetzt sowie alle Symbole (Variablen- und Sprungadressnamen) entfernt.
Programmbibliotheken und ihre Inhalte können, abhängig vom Betriebssystem und der Entwicklungsumgebung, in unterschiedlichen Formen und Strukturen gespeichert werden, zum Beispiel:
„Statische Bibliothek“ wird eine Programmbibliothek genannt, die Module/Unterprogramme enthält, die durch einen so genannten Linker (von englisch „to link“: verknüpfen) mit dem Kompilat eines anderen Programms verbunden werden. Dabei erzeugt der Linker, in der Regel für ein Hauptprogramm, eine ausführbare Datei oder (je nach Betriebssystem) ein Lademodul in einer Ladebibliothek, in der die von diesem aufgerufenen Module fest (statisch) eingebunden/angehängt sind.
Ein optimierender Linker sucht aus den zugeordneten Objekt-Modulen (Bibliotheksdateien) nur jene Komponenten (Unterprogramme oder Daten) heraus, die vom Programm auch tatsächlich aufgerufen (referenziert) werden (und für die es im Programm keine überschreibende Implementierung gibt) und hängt sie dann an das Programm an. Die so entstehende Datei wird entsprechend größer. Einfache Linker fügen einfach das komplette Objekt-Modul bzw. die komplette Bibliothek hinzu und vergrößern das Programm dadurch noch mehr.
Eine statische Bibliothek ist im Allgemeinen selbst Ergebnis aus Quelltexten, aufgeteilt in mehrere Module, deren Kompilate (Objektmodule) dann vom Linker zu der Bibliothek zusammengefügt wurden.
Kommerzielle Anbieter von Frameworks, die den Quellcode ihrer Funktionen nicht offenlegen möchten, stellen diese den Entwicklern üblicherweise in Form von statischen Bibliotheken und den zugehörigen Header-Dateien bereit. Dadurch haben Software-Entwickler die Möglichkeit, die gebotenen Funktionen in ihren Programmen zu verwenden und in Binärform in ihre Programme einzubauen, ohne dass neben den Definitionen der Quellcode der Funktionen vorliegen muss.
Hardware-Hersteller, die ihre Schnittstellen nicht offenlegen möchten, bieten durch die Bereitstellung statischer Bibliotheken eine Möglichkeit, um Treiber für neue Betriebssystem-Kernel bereitzustellen, ohne selbst bei Updates tätig werden zu müssen. Damit ist es beispielsweise auf Linux-Systemen mit Hilfe vom DKMS möglich, Kernel-Module zu bauen, die die Anforderungen der gegebenen Kernel-Version erfüllen, ohne dass der komplette Quellcode vorliegen muss. Dies betrifft u. a. die Grafiktreiber von NVIDIA.
Aus dynamischen Bibliotheken werden Komponenten erst während der Laufzeit eines Programms über einen sogenannten Lader in den Arbeitsspeicher geladen. Das geschieht entweder durch eine explizite Anweisung durch das Programm oder implizit durch einen so genannten Laufzeit-Lader, wenn das Programm dynamisch gebunden wurde. Heutzutage geschieht dies meist mit Betriebssystem-Unterstützung, da (siehe unten) dynamische Bibliotheken gesondert behandelt werden bzgl. Swapping und Einblendung in den Programm-Adressraum. Der Lader ist somit heute meist zu weiten Teilen eine Betriebssystem-Komponente.
Dynamisch gebundene Programme müssen sich um das Laden der benötigten dynamischen Komponenten nicht selbst kümmern. Beim dynamischen Binden werden Bibliothek und Kompilat nur lose verknüpft. Statt die notwendigen Symbole (Variablen- und Sprungadressnamen) zu kopieren, wie beim statischen Binden der Fall, werden sie nur referenziert. Um das Laden der dynamischen Bibliotheken und Suchen der Symbole kümmert sich ein sogenannter Laufzeit-Binder. Das Auflösen der referenzierten Symbole geschieht entweder sofort (noch vor Start des eigentlichen Programms bzw. beim Laden aus der Bibliothek) oder lazy (faul), bei der ersten Verwendung des Symbols.
Ein typischer Anwendungsfall dafür, Bibliotheken explizit zu öffnen (die Adresse von Symbolen nach deren Namen zu suchen, um das Symbol zu verwenden), sind Plug-in-Architekturen. Ein weiteres Szenario ist eine optionale Bibliothek, die verwendet wird, falls vorhanden, deren Fehlen aber keinen Fehler darstellt.
Ein Vorteil von dynamischen Bibliotheken ist, dass Programme, die eine dynamische Bibliothek verwenden, von Fehlerbehebungen in der Bibliothek profitieren, ohne neu übersetzt werden zu müssen. Wird beispielsweise ein Fehler in der OpenSSL-Bibliothek gefunden und behoben (die entsprechende Bibliothek wurde ersetzt), so genügt ein Neustart der Programme, die diese Bibliothek verwenden, um den Fehler auch in diesen Programmen zu beheben.
Da die Dateien, in denen dynamische Bibliotheken gespeichert werden, bei der Benutzung nur gelesen und ausgeführt, aber nicht verändert werden, müssen Betriebssysteme mit virtuellem Speicher dynamische Bibliotheken nur einmal laden und können sie dann in den Adressraum aller verwendenden Prozesse einblenden. Dies ist beispielsweise bei Multitasking-Systemen vorteilhaft, wenn die Bibliotheken insgesamt sehr groß sind und von vielen Prozessen gleichzeitig verwendet werden. (Sollte die dynamische Bibliothek Zustände oder gespeicherte Daten besitzen, kann dies mit Copy-On-Write abgefangen werden.)
Viele moderne Betriebssysteme laden die dynamischen Bibliotheken jedoch nicht sofort, sondern blenden sie bei Bedarf direkt von der Festplatte aus ein – sie werden wie ausgelagerte Pages behandelt. Analog werden nicht benötigte Pages, die zu einer dynamischen Bibliothek gehören und nicht verändert wurden, einfach verworfen. Bei Bedarf können sie ja aus der Festplatte wieder geladen werden.
Programmbibliotheken stellen Komponenten in bestimmten Zusammenhängen bereit, zu denen sie bezüglich ihrer Konstruktion und ihrer Schnittstellen passen (müssen). Dementsprechend gibt es Programmbibliotheken zum Beispiel in folgenden Zusammenhängen:
Bibliotheken in Programmiersprachen enthalten Dienste, die nicht im Compiler implementiert sind, sondern in der Sprache selbst programmiert sind und mit dem Compiler zusammen oder völlig von ihm getrennt dem Programmierer zur Verfügung stehen. Im ersten Fall ist die Bibliothek meist in der Sprachbeschreibung festgelegt. Im zweiten Fall spricht man von einer externen Bibliothek.
In der Sprachbeschreibung festgelegte Bibliotheken unterscheiden sich teilweise stark im Umfang.
Sprache | Teile/Pakete | Header/Klassen | Funktionen/Methoden/Konstruktoren |
---|---|---|---|
C (C89+Amendments) | 1 | 18 | 142 |
C (C99) | 1 | 24 | 482 |
C++ | 1 | 32 + 18 (C89) | |
Java 2 (JDK 1.2) | 62 | 1.287 | ≈ 18.000 |
Java 6 | 202 | 3.850 | 21.881 |
.Net 1.0 | 41 | 3.581 | 35.470 |
.Net 1.1 | 43 | 3.818 | 37.556 |
.Net 2.0 | 51 | 7.419 | 74.607 |
.Net 3.0 | 80 | 10.639 | 102.613 |
.Net 3.5 | 98 | 11.417 | 109.657 |
Java ist eine eigene Plattform und verwendet ein Bibliothekskonzept, welches nicht an das Betriebssystem gebunden ist. Im Grunde wird nicht zwischen Programm und Bibliothek unterschieden. Alle Klassen liegen kompiliert in Form von .class-Dateien vor und werden bei Bedarf geladen. In der Regel sind Bibliotheken, wenn sie aus mehreren Klassen bestehen, in einem Java-Archiv zusammengefasst. Die Java-API selbst liegt ebenfalls in Form von Java-Archiven vor.
Da die einzelnen Klassen einer Bibliothek erst zur Laufzeit geladen werden, kann es bei der ersten Verwendung zu Verzögerungen kommen, bis die Klasse geladen und initialisiert wurde. In Java für Echtzeitsysteme, aber auch in Java SE kann der Klassenlader durch entsprechende Methodenaufrufe bestimmte oder alle notwendigen Bibliotheken beim Starten laden und sie auch nicht mehr entladen, so dass bei der Benutzung keine unerwartete Verzögerung entsteht.
Bei den Betriebssystemen Windows und OS/2 wird eine Bibliotheksdatei, die dynamisch bindet, als DLL (für Dynamic Link Library) bezeichnet. Entsprechend haben diese Dateien meist die Dateiendung .dll. Ihr Dateiformat ist New Executable (16 Bit), Linear Executable (32-Bit-OS/2) oder Portable Executable (32- bzw. 64-Bit-Windows).
Unter Windows wird zwischen mehreren Arten von DLLs unterschieden:
Einsprungs-DLLs enthalten hierbei Funktionen, während ActiveX-DLLs Klassen enthalten.
DLLs bis Windows 98 und Windows NT 4.0 können nicht kontrolliert werden – jedes Programm darf sie austauschen und kann dem Betriebssystem damit möglicherweise Schaden zufügen. Windows Me, Windows 2000 und die Folgeversionen verfügen über einen Systemschutz, der auch die DLLs einbezieht.
Vorteile
Nachteile
Auf unixartigen Betriebssystemen (wie z. B. Linux) verwenden statische Bibliotheken den Dateisuffix .a
(von „Archiv“) und können mit den UNIX-Programmen ar
und nm
angesehen und bearbeitet werden. Bei Systemen, die eine Paketverwaltung anbieten, befinden sich statische Bibliotheken oft zusammen mit den Header-Dateien in einem separaten Entwicklungs-Paket.
Für dynamische Bibliotheken ist die Bezeichnung shared library (englisch für „gemeinsam genutzte Bibliothek“) gebräuchlich. Sehr verbreitet ist das Executable and Linking Format (ELF), das Standard-Format unter anderem von Linux, FreeBSD und Solaris. Für diese Dateien hat sich die Endung .so
(von shared object, „gemeinsam genutztes Objekt“) etabliert. In der Regel folgt dem Bibliotheksnamen noch die Versionsnummer der Binärschnittstelle (ABI version), so dass mehrere Versionen einer Bibliothek gleichzeitig installiert sein können. Meta-Informationen zu einem vorliegenden .so
können bspw. mit readelf
abgefragt werden.
Shared libraries beginnen auf Linux (mit Ausnahme einiger Low-Level-Bibliotheken) üblicherweise mit dem Präfix „lib
“. Die eigentliche Bibliotheksdatei enthält die volle Versionsnummer. Symbolische Verknüpfungen ermöglichen den Zugriff über den so
-Namen, sowie den Zugriff ganz ohne Versionsangabe. Beispiel:
libfoo.so -> libfoo.so.1
libfoo.so.1 -> libfoo.so.1.2.3
libfoo.so.1.2.3
Der so
-Name ist in dem Fall „libfoo.so.1
“. Die Zahl nach „.so.
“ ändert sich nur dann, wenn sich in einer neuen Version die Schnittstelle der Bibliothek ändert.
Der Laufzeit-Linker wählt anhand von Versions-Informationen im auszuführenden Programm bzw. in der zu ladenden Bibliothek eine Version mit einer kompatiblen Schnittstelle aus. Da sowohl Programme von Bibliotheken abhängen können, als auch Bibliotheken von weiteren Bibliotheken, kann eine Software indirekt von vielen Bibliotheken abhängen. Da viele Unixoide Systeme die Bibliotheken zentral für Betriebssystem und Applikation zusammen verwalten, existieren Paketverwaltungen, die Abhängigkeiten berechnen und benötigte Bibliotheken automatisch installieren können. Beispiele für derartige Paketverwaltungs-Systeme sind APT und YUM.
Von welchen Bibliotheken ein Programm direkt abhängt, lässt sich auf einigen Systemen mit Hilfe des UNIX-Programms ldd
herausfinden.
Bei Software, die in der Binärversion vertrieben werden soll, beispielsweise kommerzielle Closed-Source-Software oder portable/distributionunabhängige Software, muss gewährleistet werden, dass alle benötigten Bibliotheken vorliegen. Das Anwendersystem, auf dem diese Software verwendet werden soll, muss dann als kompatible Binärplattform agieren können. Dies kann folgendermaßen geschehen:
LD_LIBRARY_PATH
über ein Skript oder händisch.[5]$ORIGIN
erzeugt werden.[5]Objekt- und komponentenorientierte Ansätze können hier realisiert werden, indem in einer Funktion das entsprechende Objekt oder die Komponente instantiiert und zurückgegeben werden.
Vorteile
Nachteile
Bei z/OS wie auch in den Vorgängersystemen System/360 und System/390 werden/wurden Programmbibliotheken (wie alle Arten von Bibliotheken) in der Form von Partitioned Data Sets (PDS) geführt. Je Programmcode-Typ (siehe unten) werden i. d. R. eigene Bibliotheken benutzt und deren Elemente typneutral als Member bezeichnet. Die Members werden von verschiedenen Systemprogrammen der Entwicklungsumgebung dort eingestellt und von dort verwendet.
Je Programmcode-Typ wird – je nach Bedarf – eine (1) Bibliothek für ein ganzes Unternehmen, je Unternehmensbereich oder für bestimmte Anwendungsgebiete verwendet. Die Unterscheidung der Einträge erfolgt über den Membernamen. Es werden zum Beispiel folgende Arten von Programmbibliotheken benutzt:
Beim AmigaOS werden alle Bibliotheken als shared Library verwendet. Sie werden also zur Laufzeit vom Programm beim System angefordert, das dann die Basisadresse der Bibliothek im Speicher (bis OS3.9) oder die entsprechende Schnittstelle (ab OS4.0) zur Verfügung stellt. Das Programm verwendet dann relative Adressen, um über eine Sprungtabelle vor der Basisadresse an die eigentlichen Funktionen (hinter der Basisadresse) zu kommen. Diese Funktionen sind eintrittsinvariant (reentrant).
Selbst bei Änderungen der Bibliothek sind die bestehenden Einträge der Sprungtabellen immer gleich. Es kommen ggf. lediglich neue Einträge hinzu am Ende der Tabellen. Somit ist eine Abwärtskompatibilität gegeben.
Als Besonderheit kann bei AmigaOS beim Öffnen einer Library eine Mindest-Versionsnummer angegeben und so sichergestellt werden, dass eine gewünschte Funktionalität auch wirklich verfügbar ist. Wird diese Version nicht vorgefunden, kann das aufrufende Programm sicher auf eine einfachere Funktionalität, wie sie in der älteren Library-Version bereitgestellt wird, zurückschalten.
Bibliotheksdateien tragen die Endung .library und befinden sich meist im Verzeichnis LIBS: der Systempartition. Das Betriebssystem überprüft bei der Suche nach einer Bibliothek auch das Programmverzeichnis des anfragenden Programms.
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.