Procesul de legare expus – Biblioteci statice vs. dinamice

oct. 19, 2021
admin

Crearea unei biblioteci statice și dinamice

Pentru o bibliotecă statică, codul obiect din fișierele binare (extensia .o) sunt combinate într-un singur fișier de arhivă cu extensia .a. Această arhivă este similară cu o cutie de instrumente care conține toate instrumentele care ar putea fi utilizate în programele care apelează biblioteca respectivă în timpul legăturii. Instrumentele sunt inserate în locurile în care sunt necesare. În imaginea de mai jos, am o serie de fișiere .c.

Din moment ce o bibliotecă este o arhivă de cod obiect, trebuie să convertesc toate aceste fișiere .c în fișiere .o folosind următoarea comandă:

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

Opțiunea -c oprește procesul de compilare chiar înainte de legare, după ce sunt generate fișierele de cod obiect. Acum am toate fișierele de cod obiect:

Dacă execut comanda ar -rc libholbertonschool.a *.o, pot arhiva aceste fișiere într-un singur fișier de bibliotecă .a. Comanda ar este pentru arhivare, opțiunea -r este pentru a muta membrii care au extensia .o, iar opțiunea -c este pentru a crea arhiva dacă aceasta nu există. Un fișier de bibliotecă începe cu prefixul lib și are extensia .a. Ultimul pas care este necesar pe unele sisteme este de a indexa conținutul arhivei pentru a grăbi crearea legăturii. Acest lucru se poate face cu ranlib libholbertonschool.a. Acum am o bibliotecă ce conține codul obiect pentru toate funcțiile din imaginea de mai sus.

Utilizarea bibliotecii statice

Pentru a utiliza această bibliotecă cu un fișier de test oarecare, trebuie să compilez fișierul de test cu biblioteca folosind una din următoarele două comenzi:

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

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

Ambele fac același lucru, dar a doua este puțin mai criptică. Opțiunea -L. caută bibliotecile din directorul curent, iar opțiunea -l, care este legată de holbertonschool, caută implicit fișierul de bibliotecă, unde se presupune un prefix lib și un sufix .a. Fără compilarea cu un fișier de bibliotecă, gcc va arunca o eroare deoarece funcțiile pe care încearcă să le lege nu sunt furnizate. Prin furnizarea unei biblioteci la compilare, compilatorul poate acum să caute în bibliotecă funcțiile de care are nevoie și să le insereze acolo unde este nevoie.

Biblioteci dinamice

Crearea bibliotecilor dinamice este ușor diferită de bibliotecile statice, dar conceptele sunt în general aceleași. Am același număr de fișiere .c și fișierul antet care definește prototipurile lor într-un fișier numit lists.h.

Pentru a crea biblioteca dinamică, care are un .so (care reprezintă obiectul partajat), se poate introduce următoarea comandă de compilare:

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

Semnalizatorul -fPIC reprezintă Codul independent de poziție, care este necesar pentru legarea dinamică. Semnificația acestuia este exact ceea ce pare – deoarece bibliotecile legate dinamic pot fi stocate oriunde în memorie unde se potrivesc, acest indicator permite ca fișierul de bibliotecă să fie utilizat indiferent de locul în care este stocat.

Indicatorul -shared permite crearea unei arhive partajate, iar opțiunea -o ne permite să redenumim fișierul de ieșire în libholberton.so.

După ce am executat această comandă, acum am o bibliotecă partajată!

Utilizarea bibliotecii dinamice

Să spunem că am următorul cod:

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

Pot compila programul cu următorul cod:

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

La fel ca în cazul bibliotecilor statice, opțiunile -L. caută în director fișierele de bibliotecă, iar -l care este atașat la începutul lui holberton este o căutare implicită a fișierelor de bibliotecă care au prefixul lib, sufixul .so și holberton între cele două.

Pentru a utiliza fișierul de bibliotecă pe care tocmai l-am creat, trebuie să mă asigur că compilatorul este capabil să găsească toate fișierele de bibliotecă în memorie și că acestea sunt încărcate corect în memorie pentru început. Dacă execut ldd len acum, pot vedea următoarele:

Linia libholberton.so => not found îmi spune că dependența de biblioteca dinamică pe care tocmai am creat-o nu este îndeplinită. Pentru a remedia acest lucru, trebuie înțeleasă variabila de mediu $LD_LIBRARY_PATH. În Linux, această variabilă este o listă de directoare, separate prin două puncte, în care sistemul caută fișiere de bibliotecă. În imaginea de mai sus, puteți vedea că ecoul acestei variabile la starea actuală arată că este goală și, astfel, încercarea mea de a rula programul (len) nu funcționează deoarece biblioteca partajată nu poate fi încărcată.

Directorul meu curent arată astfel:

După cum puteți vedea, fișierul de bibliotecă se află în același director cu fișierul meu principal și cu fișierul de antet (directorul de lucru curent). Observați următoarea imagine:

Comanda export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH actualizează variabila de mediu $LD_LIBRARY_PATH cu un .: care indică faptul că sistemul trebuie să caute bibliotecile în directorul de lucru curent. Comanda export face ca această modificare să fie globală, astfel încât orice shell poate accesa aceeași valoare. Astfel, atunci când fac ecoul variabilei, văd actualizările mele. Executând din nou ldd len, văd că libholberton.so se află la locația de adresă 0x00007fb9216b9000, care este probabil locația sa în directorul de lucru curent din memorie. Astfel, dependența executabilului de biblioteca partajată este acum îndeplinită, iar programul returnează 9 care este lungimea cuvântului „Holberton„.

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.