Hlavní navigace

Programování pod Linuxem pro všechny (4)

Jakub Matys

V dnešním dílu probereme knihovny. Zabývat se budeme vytvářením a použitím knihoven dynamických a statických. Jelikož toto téma je poněkud rozlehlejší, dokončení se dočkáte až v dílu následujícím. Pokud nevíte, co to knihovny jsou a jak se používají, hurá na to...

Název knihovny je v podstatě oprávněný, protože knihovny „počítačové“ se chovají jako knihovny „knižní“. Představte si část programového kódu (např. funkci) jako knihu, kterou máte založenou v knihovně podle určitého systému. Pokud potřebujete použít tuto knihu, jednoduše přijdete, sáhnete přesně tam, kam máte, a knihu použijete.

Knihovny umožňují programátorům efektivněji pracovat. Programátor nemusí vymýšlet nové algoritmy, pokud jej již někdo předešel a svůj algoritmus uložil do knihovny. Tímto systémem je také zajištěna přenositelnost programů. Programátor nemusí znát do podrobností architekturu počítače, pro který je program psán, stačí, pokud zná příslušné knihovny. Samotný jazyk C je navržen tak, že maximálně využívá výhod knihoven.

Knihovny jsou statické a dynamické (sdílené); jak samotný název napovídá statické knihovny jsou určeny k „pevnému“ připojení ke kódu a dynamické se zavádějí, jen když je jich potřeba. Všechny knihovny v systému Linux mají předponu lib a některou ze dvou přípon, podle typu knihovny.

Statické knihovny

Statické knihovny jsou vlastně jednoduchou kolekcí přemístitelného kódu uloženého v jediném souboru, proto se někdy též nazývají archivy. Když spojovacímu programu specifikujete nějakou statickou knihovnu, bude v ní program vyhledávat kódy funkcí, jež používáte ve svém programu. Vyhledanou funkci extrahuje a spojí ji s vaším programem stejně, jako byste přemístitelný kód specifikovali spojovacímu programu odděleně.

Pro vytvoření statické knihovny můžete použít program ar. Statické knihovny používají příponu .a. Následující příklad vytváří ze souborů test1.o a test2.o knihov­nulibtest.a.

# ar cr libtest.a test1.o test2.o

Menší přehled voleb programu ar:

  • c … vytvoří nový archiv
  • r … vloží soubory do archivu
  • d … maže moduly podle jejich jména
  • t … vypíše tabulku modulů, ze kterých byl archiv vytvořen
  • p … vypíše specifikované položky archivu na standardní výstup

Při spojování programů s knihovnami se používá program ld. Jeho použítí má však jednu záludnost. Když program identifikuje v příkazovém řádku statickou knihovnu, vyhledá v ní všechny definice a symboly, na které našel odkazy v doposud zpracovaném přemístitelném kódu a které nemá doposud definovány. Přemístitelné kódy definující tyto symboly vyjme ze statické knihovny a spojí je s výsledným spustitelným kódem. Je tedy důležité specifikovat v příkazovém řádku statické knihovny jako poslední, jinak se překlad nezdaří.

Dynamické/sdílené knihovny

Dynamické knihovny jsou podobné knihovnám statickým v tom smyslu, že obsahují kolekci přemístitelných kódů. Ale program používající dynamickou knihovnu vlastně vůbec neobsahuje její kód. Obsahuje jen odkaz na tento kód v dynamické knihovně. A je celkem samozřejmé, že dynamické knihovny může naráz využívat několik současně běžících programů (odtud termín sdílená knihovna).

Další důležitou informací je, že dynamická knihovna není pouhou kolekcí přemístitelných kódů, z nichž si spojovací program vybírá odkazy na nedefinované symboly. V dynamické knihovně jsou přemístitelné kódy spojeny do jediného celku a program tak má v době své realizace k dispozici všechen kód obsažený v knihovně.

Chceteli vytvořit dynamickou knihovnu, musíte nejdříve její moduly přeložit speciálním způsobem – s použižím volby -fPIC:

# gcc -c -fPIC test1.c

Zkratka PIC označuje Position-Independent Code(kód nezávislý na pozici). Co to znamená? Funkce ve sdílené knihovně mohou být zavedeny do paměti na různých pozicích. Proto kód těchto funkcí nesmí záviset na pozici v paměti.

Po překladu lze přemístitelné kódy spojit do jediného souboru, tedy do dynamické knihovny:

# gcc -shared -fPIC -o libtest.so test1.o test2.o

Volba -shared sděluje programu ld, že má vytvořit sdílenou knihovnu a nikoliv spustitelný kód. Sdílené knihovny mají příponu .so (shared object).

Spojování kódu s dynamickými knihovnami je stejné jako spojování se statickými knihovnami:

# gcc -o egg -egg.o -L. -ltest

Předpokládejme nyní, že existují dynamická knihovna libtest.so i statická knihovna libtest.a. Spojovací program bude prohledávat adresáře (nejdříve ten, který je uveden za volbou -L, pak systémové), dokud nenajde adresář obsahující libtest.a nebo libtest.so, pak prohledávání ukončí. Pokud se v daném adresáři nachází pouze první z uvedených knihoven, spojovací program si ji vybere. Jinak si vybere druhou knihovnu, je-li přítomna. Abyste se vyhnuli těmto nejasnostem s vybíráním knihoven, můžete zvolit při překladu volbu -static. Při zapnutí této volby bude použita jen statická knihovna, i když je v adresáři přítomna dynamická.

# gcc -static -o egg egg.o -L. -ltest

Pomocí příkazu ldd si můžete vypsat seznam všech sdílených knihoven, které jsou spojeny s daným spustitelným programem. V seznamu dynamických knihoven se vždy zobrazí knihovna ld-linux.so, která je standardní součástí spojovacího mechanismu v systému GNU/Linux.

To by bylo pro dnešek vše. V příštím dílu dokončím pasáž o knihovnách vysvětlením použití proměnné LD_LIBRARY_PATH a zavádění dynamických knihoven za běhu programu. A pokud zbude nějaké místo, začnu s úvodem do práce s procesy.

Našli jste v článku chybu?