Il processo di collegamento esposto – Librerie statiche vs. dinamiche

Ott 19, 2021
admin

Creazione di una libreria statica e dinamica

Per una libreria statica, il codice oggetto dei file binari (estensione .o) sono combinati in un singolo file archivio con estensione .a. Questo archivio è simile a un toolbox che contiene tutti gli strumenti che potrebbero essere usati nei programmi che chiamano quella libreria durante il collegamento. Gli strumenti sono inseriti nei posti in cui sono necessari. Nell’immagine qui sotto, ho una serie di file .c.

Siccome una libreria è un archivio di codice oggetto, ho bisogno di convertire tutti questi file .c in file .o usando il seguente comando:

gcc -Wall -Wextra -Werror -pedantic -c *.c

L’opzione -c ferma il processo di compilazione proprio prima del collegamento dopo che i file di codice oggetto sono generati. Ora ho tutti i file di codice oggetto:

Se eseguo il comando ar -rc libholbertonschool.a *.o, posso archiviare questi file in un unico file di libreria .a. Il comando ar serve ad archiviare, l’opzione -r serve a spostare i membri che hanno estensione .o, e l’opzione -c serve a creare l’archivio se non esiste. Un file di libreria inizia con un prefisso lib e ha un’estensione .a. Il passo finale che è necessario su alcuni sistemi è quello di indicizzare il contenuto dell’archivio per velocizzare il collegamento. Questo può essere fatto con ranlib libholbertonschool.a. Ora ho una libreria che contiene il codice oggetto per tutte le funzioni nell’immagine sopra.

Usare la libreria statica

Per usare questa libreria con qualche file di prova, devo compilare il file di prova con la libreria usando uno dei due seguenti comandi:

gcc test.c ./libholbertonschool.a -o exename

gcc test.c -L. -lholbertonschool -o exename

Entrambi fanno la stessa cosa, ma il secondo è leggermente più criptico. L’opzione -L. cerca le librerie nella directory corrente e l’opzione -l che è collegata a holbertonschool cerca il file di libreria implicitamente dove si assume un prefisso lib e un suffisso .a. Senza compilare con un file di libreria, gcc darà un errore poiché le funzioni che sta cercando di collegare non sono fornite. Fornendo una libreria nella compilazione, il compilatore può ora cercare nella libreria le funzioni di cui ha bisogno e inserirle dove sono necessarie.

Biblioteche dinamiche

Creare librerie dinamiche è leggermente diverso dalle librerie statiche, ma i concetti sono generalmente gli stessi. Ho lo stesso numero di file .c e il file header che definisce i loro prototipi in un file chiamato lists.h.

Per creare la libreria dinamica, che ha un .so (che sta per oggetto condiviso), si può inserire il seguente comando di compilazione:

gcc -fPIC -Wall -Werror -Wextra -pedantic *.c -shared -o libholberton.so

La bandiera -fPIC sta per Position Independent Code che è richiesta per il collegamento dinamico. Il significato di questo è esattamente quello che sembra – poiché le librerie collegate dinamicamente possono essere memorizzate ovunque nella memoria dove si adattano, questo flag permette al file della libreria di essere usato indipendentemente da dove è memorizzato.

Il flag -shared permette di creare un archivio condiviso e l’opzione -o ci permette di rinominare il file di output in libholberton.so.

Dopo aver eseguito questo comando, ora ho una libreria condivisa!

Utilizzando la libreria dinamica

Diciamo che ho il seguente codice:

#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);
}

Posso compilare il programma con il seguente codice:

gcc -Wall -pedantic -Werror -Wextra -L. 0-main.c -lholberton -o len 

Proprio come le librerie statiche, le opzioni -L. cercano i file di libreria nella directory e il -l che è aggiunto all’inizio di holberton è una ricerca implicita dei file di libreria che hanno un prefisso lib, un suffisso .so, e holberton tra i due.

Per usare il file di libreria che ho appena creato, devo assicurarmi che il compilatore sia in grado di trovare tutti i file di libreria in memoria e che siano correttamente caricati in memoria per cominciare. Se ora eseguo ldd len, posso vedere quanto segue:

La linea libholberton.so => not found mi dice che la dipendenza dalla libreria dinamica appena creata non è soddisfatta. Per risolvere questo problema, la variabile ambientale $LD_LIBRARY_PATH deve essere compresa. In Linux, questa variabile è una lista separata da due punti di directory in cui il sistema cerca i file di libreria. Nell’immagine qui sopra, potete vedere che l’eco di questa variabile allo stato attuale mostra che è vuota e quindi, il mio tentativo di eseguire il programma (len) non funziona perché la libreria condivisa non può essere caricata.

La mia directory corrente si presenta così:

Come potete vedere, il file della libreria si trova nella stessa directory del mio file principale e del file header (directory di lavoro corrente). Osservate la seguente immagine:

Il comando export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH aggiorna la variabile ambientale $LD_LIBRARY_PATH con un .: che indica che il sistema deve cercare le librerie nella directory di lavoro corrente. Il comando export rende questo cambiamento globale in modo che qualsiasi shell possa accedere allo stesso valore. Così, quando faccio l’echo della variabile, vedo i miei aggiornamenti. Eseguendo ldd len di nuovo, vedo che libholberton.so è alla posizione dell’indirizzo 0x00007fb9216b9000 che è probabilmente la sua posizione nella directory di lavoro corrente in memoria. Così, la dipendenza dell’eseguibile dalla libreria condivisa è ora soddisfatta e il programma restituisce 9 che è la lunghezza della parola “Holberton“.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.