A linkelési folyamat feltárása – Statikus vs. dinamikus könyvtárak

okt 19, 2021
admin

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.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.