Länkningsprocessen avslöjad – statiska och dynamiska bibliotek
Skapa ett statiskt och dynamiskt bibliotek
För ett statiskt bibliotek kombineras objektkoden från binära filer (filändelse .o
) i en enda arkivfil med filändelse .a
. Detta arkiv liknar en verktygslåda som innehåller alla verktyg som kan användas i program som anropar biblioteket under länkningen. Verktygen infogas på de ställen där de behövs. I bilden nedan har jag en serie .c
-filer.
Då ett bibliotek är ett arkiv med objektkod måste jag konvertera alla dessa .c
-filer till .o
-filer med hjälp av följande kommando:
gcc -Wall -Wextra -Werror -pedantic -c *.c
Optionen -c
stoppar kompileringsprocessen precis före länkning efter att objektkodsfiler har genererats. Jag har nu alla objektkodfiler:
Om jag kör kommandot ar -rc libholbertonschool.a *.o
kan jag arkivera dessa filer i en enda .a
biblioteksfil. Kommandot ar
är för arkivering, alternativet -r
är för att flytta medlemmar som har tillägget .o
och alternativet -c
är för att skapa arkivet om det inte finns. En biblioteksfil börjar med prefixet lib
och har tillägget .a
. Det sista steget som är nödvändigt på vissa system är att indexera arkivets innehåll för att påskynda länkningen. Detta kan göras med ranlib libholbertonschool.a
. Jag har nu ett bibliotek som innehåller objektkod för alla funktioner i bilden ovan.
Användning av det statiska biblioteket
För att använda det här biblioteket med någon testfil måste jag kompilera testfilen med biblioteket med hjälp av något av följande två kommandon:
gcc test.c ./libholbertonschool.a -o exename
gcc test.c -L. -lholbertonschool -o exename
Båda dessa gör samma sak, men det andra är något mer kryptiskt. Alternativet -L.
söker efter bibliotek i den aktuella katalogen och -l
som är kopplat till holbertonschool
söker implicit efter biblioteksfilen där ett lib
prefix och .a
suffix antas. Utan att kompilera med en biblioteksfil kommer gcc
att ge ett fel eftersom de funktioner som den försöker länka inte finns med. Genom att tillhandahålla ett bibliotek i kompileringen kan kompilatorn nu söka i biblioteket efter de funktioner den behöver och infoga dem där de behövs.
Dynamiska bibliotek
Skapandet av dynamiska bibliotek skiljer sig något från statiska bibliotek, men koncepten är i stort sett desamma. Jag har samma antal .c
-filer och den header-fil som definierar deras prototyper i en fil som heter lists.h
.
För att skapa det dynamiska biblioteket, som har ett .so
(som står för delat objekt), kan följande kompileringskommando skrivas in:
gcc -fPIC -Wall -Werror -Wextra -pedantic *.c -shared -o libholberton.so
Flaggan -fPIC
står för positionsoberoende kod, som krävs för dynamisk länkning. Innebörden av detta är exakt vad det låter som – eftersom dynamiskt länkade bibliotek kan lagras var som helst i minnet där de passar, gör denna flagga det möjligt att använda biblioteksfilen oavsett var den lagras.
Flaggan -shared
gör det möjligt att skapa ett delat arkiv och alternativet -o
gör det möjligt för oss att döpa om utdatafilen till libholberton.so
.
Efter att ha kört detta kommando har jag nu ett delat bibliotek!
Användning av det dynamiska biblioteket
Vad sägs om att jag har följande kod:
#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);
}
Jag kan kompilera programmet med följande kod:
gcc -Wall -pedantic -Werror -Wextra -L. 0-main.c -lholberton -o len
När det gäller de statiska biblioteken söker -L.
-alternativet i katalogen efter biblioteksfiler och -l
som läggs till i början av holberton
är en implicit sökning efter biblioteksfiler som har prefixet lib
, suffixet .so
och holberton
mellan de två.
För att kunna använda den biblioteksfil som jag just skapat måste jag se till att kompilatorn kan hitta alla biblioteksfiler i minnet och att de är korrekt inlästa i minnet till att börja med. Om jag kör ldd len
nu kan jag se följande:
Raden libholberton.so => not found
talar om för mig att beroendet av det dynamiska biblioteket som jag just har skapat inte är uppfyllt. För att åtgärda detta måste miljövariabeln $LD_LIBRARY_PATH
förstås. I Linux är den här variabeln en kolonseparerad lista över kataloger som systemet letar efter biblioteksfiler. I bilden ovan kan du se att ett eko av denna variabel i det aktuella läget visar att den är tom och därmed fungerar inte mitt försök att köra programmet (len
) eftersom det delade biblioteket inte kan laddas.
Min nuvarande katalog ser ut så här:
Som du kan se ligger biblioteksfilen i samma katalog som min huvudfil och min header-fil (nuvarande arbetskatalog). Observera följande bild:
Kommandot export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
uppdaterar miljövariabeln $LD_LIBRARY_PATH
med ett .:
som anger att systemet ska söka i den aktuella arbetskatalogen efter bibliotek. Kommandot export
gör den här ändringen global så att alla skal kan få tillgång till samma värde. När jag ekar variabeln ser jag alltså mina uppdateringar. När jag kör ldd len
igen ser jag att libholberton.so
befinner sig på adressplats 0x00007fb9216b9000
, vilket sannolikt är dess plats i den aktuella arbetskatalogen i minnet. Således är det körbara programmets beroende av det delade biblioteket nu uppfyllt och programmet returnerar 9
som är längden på ordet ”Holberton
”.