A linkelési folyamat feltárása – Statikus vs. dinamikus könyvtárak
Sztatikus és dinamikus könyvtár létrehozása
A statikus könyvtár esetében a bináris fájlok (kiterjesztés .o
) objektumkódja egyetlen, .a
kiterjesztésű archív fájlban egyesül. Ez az archívum egy eszköztárhoz hasonlít, amely tartalmazza az összes olyan eszközt, amelyet az adott könyvtárat a linkelés során meghívó programokban használhatunk. Az eszközök oda kerülnek be, ahol szükség van rájuk. Az alábbi képen egy sor .c
fájlom van.

Mivel a könyvtár egy objektumkódot tartalmazó archívum, az összes ilyen .c
fájlt át kell alakítanom .o
fájlokká a következő parancs segítségével:
gcc -Wall -Wextra -Werror -pedantic -c *.c
A -c
opció közvetlenül a linkelés előtt leállítja a fordítási folyamatot az objektumkód fájlok létrehozása után. Most már megvan az összes objektumkód fájl:

Ha a ar -rc libholbertonschool.a *.o
parancsot futtatom, akkor ezeket a fájlokat egyetlen .a
könyvtárfájlba archiválhatom. A ar
parancs az archiválásra, a -r
opció a .o
kiterjesztésű tagok áthelyezésére, a -c
opció pedig az archívum létrehozására szolgál, ha az még nem létezik. Egy könyvtárfájl lib
előtaggal kezdődik, és .a
kiterjesztéssel rendelkezik. Az utolsó lépés, amely egyes rendszereken szükséges, az archívum tartalmának indexelése a linkelés felgyorsítása érdekében. Ezt a ranlib libholbertonschool.a
segítségével lehet elvégezni. Most már van egy könyvtáram, amely a fenti képen látható összes függvény objektumkódját tartalmazza.
A statikus könyvtár használata
Hogy ezt a könyvtárat valamilyen tesztfájllal használjam, a tesztfájlt a könyvtárral kell lefordítanom a következő két parancs valamelyikével:
gcc test.c ./libholbertonschool.a -o exename
gcc test.c -L. -lholbertonschool -o exename
Mindkettő ugyanazt teszi, de a második kicsit rejtélyesebb. A -L.
opció az aktuális könyvtárban lévő könyvtárakat keresi, a holbertonschool
-hez kapcsolódó -l
pedig implicit módon keresi a könyvtárfájlt, ahol lib
előtagot és .a
utótagot feltételez. Könyvtárfájllal való fordítás nélkül a gcc
hibát fog dobni, mivel a linkelni kívánt függvények nincsenek megadva. Ha a fordítás során megadunk egy könyvtárat, akkor a fordító most meg tudja keresni a könyvtárban a szükséges függvényeket, és be tudja illeszteni őket oda, ahol szükség van rájuk.
Dinamikus könyvtárak
A dinamikus könyvtárak létrehozása némileg eltér a statikus könyvtáraktól, de a fogalmak általában ugyanazok. Ugyanannyi .c
fájlom van, és a prototípusaikat definiáló fejlécfájl egy lists.h
nevű fájlban.

A dinamikus könyvtár létrehozásához, amely .so
(a megosztott objektumot jelöli), a következő fordítási parancsot adhatjuk meg:
gcc -fPIC -Wall -Werror -Wextra -pedantic *.c -shared -o libholberton.so
A -fPIC
jelző a pozíciófüggetlen kódot jelenti, amely a dinamikus linkeléshez szükséges. Ennek jelentése pontosan az, aminek hangzik – mivel a dinamikusan linkelt könyvtárak bárhol tárolhatók a memóriában, ahol elférnek, ez a flag lehetővé teszi, hogy a könyvtárfájlt a tárolási helyétől függetlenül használjuk.
A -shared
flag lehetővé teszi egy megosztott archívum létrehozását, a -o
opcióval pedig átnevezhetjük a kimeneti fájlt libholberton.so
-re.
A parancs futtatása után már van egy megosztott könyvtáram!

A dinamikus könyvtár használata
Tegyük fel, hogy a következő kóddal rendelkezem:
#include "holberton.h"
#include <stdlib.h>
#include <stdio.h>/**
* main - check the code for Holberton School students.
*
* Return: Always EXIT_SUCCESS.
*/
int main(void)
{
printf("%d\n", _strlen("Holberton"));
return (EXIT_SUCCESS);
}
A programot a következő kóddal tudom lefordítani:
gcc -Wall -pedantic -Werror -Wextra -L. 0-main.c -lholberton -o len
A statikus könyvtárakhoz hasonlóan a -L.
opciók könyvtárfájlokat keresnek a könyvtárban, a holberton
elejére illesztett -l
pedig implicit módon olyan könyvtárfájlokat keres, amelyek előtagja lib
, utótagja .so
, és a kettő között holberton
.
Az imént létrehozott könyvtárfájl használatához meg kell győződnöm arról, hogy a fordító képes megtalálni az összes könyvtárfájlt a memóriában, és hogy azok kezdetben megfelelően be vannak töltve a memóriába. Ha most lefuttatom a ldd len
sort, a következőket látom:

A libholberton.so => not found
sor azt mondja, hogy az imént létrehozott dinamikus könyvtár függősége nem teljesül. Ennek kijavításához a $LD_LIBRARY_PATH
környezeti változót kell megérteni. Linuxban ez a változó egy kettősponttal elválasztott lista azokról a könyvtárakról, amelyekben a rendszer könyvtárfájlokat keres. A fenti képen látható, hogy ennek a változónak a visszhangja a jelenlegi állapotában azt mutatja, hogy üres, és így a program futtatására tett kísérletem (len
) nem működik, mert a megosztott könyvtár nem tölthető be.
Az aktuális könyvtáram így néz ki:

Amint látható, a könyvtárfájl ugyanabban a könyvtárban található, mint a fő- és fejlécfájlom (aktuális munkakönyvtár). Figyeljük meg a következő képet:

A export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
parancs frissíti a $LD_LIBRARY_PATH
környezeti változót egy .:
-val, ami azt jelzi, hogy a rendszer keressen könyvtárakat az aktuális munkakönyvtárban. A export
parancs ezt a módosítást globálisvá teszi, így bármelyik shell elérheti ugyanazt az értéket. Így amikor visszahallgatom a változót, látom a frissítéseimet. A ldd len
ismételt futtatásával látom, hogy a libholberton.so
a 0x00007fb9216b9000
címhelyen van, ami valószínűleg az aktuális munkakönyvtárban lévő helye a memóriában. Így a végrehajtható program függősége a megosztott könyvtárral szemben most teljesül, és a program 9
-et ad vissza, ami a “Holberton
” szó hossza.