Linkitysprosessi paljastuu – staattiset ja dynaamiset kirjastot

loka 19, 2021
admin

Statisen ja dynaamisen kirjaston luominen

Staattisessa kirjastossa binääritiedostojen (tiedostopääte .o) objektikoodi yhdistetään yhdeksi arkistotiedostoksi, jonka tiedostopääte on .a. Tämä arkisto muistuttaa työkalupakkia, joka sisältää kaikki työkalut, joita voidaan käyttää ohjelmissa, jotka kutsuvat kyseistä kirjastoa linkityksen aikana. Työkalut lisätään paikkoihin, joissa niitä tarvitaan. Alla olevassa kuvassa minulla on sarja .c-tiedostoja.

Koska kirjasto on objektikoodin arkisto, minun on muunnettava kaikki nämä .c-tiedostot .o-tiedostoiksi seuraavalla komennolla:

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

Vaihtoehto -c pysäyttää käännöksen kääntämisen juuri ennen linkittämistä sen jälkeen, kun objektikooditiedostot on luotu. Minulla on nyt kaikki objektikooditiedostot:

Jos suoritan komennon ar -rc libholbertonschool.a *.o, voin arkistoida nämä tiedostot yhteen .a-kirjastotiedostoon. Komento ar on arkistointia varten, -r-vaihtoehto siirtää jäsenet, joilla on pääte .o, ja -c-vaihtoehto luo arkiston, jos sitä ei ole olemassa. Kirjastotiedosto alkaa etuliitteellä lib ja sillä on .a-pääte. Viimeinen vaihe, joka on tarpeen joissakin järjestelmissä, on indeksoida arkiston sisältö linkittämisen nopeuttamiseksi. Tämä voidaan tehdä käyttämällä ranlib libholbertonschool.a. Minulla on nyt kirjasto, joka sisältää objektikoodin kaikille yllä olevan kuvan funktioille.

Staattisen kirjaston käyttäminen

Käyttääkseni tätä kirjastoa jonkin testitiedoston kanssa minun on käännettävä testitiedosto kirjaston kanssa jommallakummalla seuraavista kahdesta komennosta:

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

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

Kummallakin komennolla saadaan aikaan sama juttu, mutta jälkimmäisellä komennolla päästään hiukan enemmän kryptiseen asiaan. Vaihtoehto -L. etsii kirjastoja nykyisestä hakemistosta, ja holbertonschool:n yhteydessä oleva -l etsii implisiittisesti kirjastotiedostoa, jossa oletetaan lib-etuliite ja .a-suffiksi. Ilman kääntämistä kirjastotiedoston kanssa gcc heittää virheen, koska funktioita, joita se yrittää linkittää, ei ole annettu. Tarjoamalla kirjaston kääntämisen yhteydessä kääntäjä voi nyt etsiä kirjastosta tarvitsemansa funktiot ja lisätä ne sinne, missä niitä tarvitaan.

Dynaamiset kirjastot

Dynaamisten kirjastojen luominen eroaa hieman staattisista kirjastoista, mutta käsitteet ovat yleisesti ottaen samat. Minulla on sama määrä .c-tiedostoja ja otsikkotiedosto, joka määrittelee niiden prototyypit tiedostossa nimeltä lists.h.

Luoaksemme dynaamisen kirjaston, jossa on .so (joka tarkoittaa jaettua objektia), voidaan syöttää seuraava kääntämiskomento:

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

Lippukirjain -fPIC tarkoittaa Position Independent Code (sijainnista riippumaton koodi), joka vaaditaan dynaamista linkitystä varten. Tämän merkitys on juuri se, miltä se kuulostaa – koska dynaamisesti linkitettyjä kirjastoja voidaan tallentaa mihin tahansa muistiin, mihin ne sopivat, tämä lippu sallii kirjastotiedoston käytön riippumatta siitä, mihin se on tallennettu.

Lippu -shared sallii jaetun arkiston luomisen, ja -o-vaihtoehdon avulla voimme nimetä tulostiedoston uudelleen muotoon libholberton.so.

Tämän komennon suorittamisen jälkeen minulla on nyt jaettu kirjasto!

Dynaamisen kirjaston käyttäminen

Sitotaan, että minulla on seuraavanlainen koodi:

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

Voin kääntää ohjelman seuraavalla koodilla:

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

Aivan kuten staattisten kirjastojen kohdalla, -L. -vaihtoehdot etsivät hakemistosta kirjastotiedostoja ja holberton:n alkuun liitetty -l on implisiittinen haku kirjastotiedostoille, joilla on etuliite lib, loppuliite .so ja holberton näiden kahden välissä.

Käyttääkseni juuri luomaani kirjastotiedostoa minun on varmistettava, että kääntäjä pystyy löytämään kaikki muistissa olevat kirjastotiedostot ja että ne on ladattu muistiin oikein aluksi. Jos suoritan nyt ldd len, näen seuraavaa:

Rivillä libholberton.so => not found kerrotaan, että äsken luomani dynaamisen kirjastokirjaston riippuvuus ei täyty. Tämän korjaamiseksi on ymmärrettävä ympäristömuuttuja $LD_LIBRARY_PATH. Linuxissa tämä muuttuja on kaksoispisteellä erotettu luettelo hakemistoista, joista järjestelmä etsii kirjastotiedostoja. Yllä olevasta kuvasta näet, että tämän muuttujan kaiku tämänhetkisessä tilassa osoittaa, että se on tyhjä ja näin ollen yritykseni suorittaa ohjelma (len) ei toimi, koska jaettua kirjastoa ei voida ladata.

Nykyinen hakemistoni näyttää tältä:

Kuten näette, kirjastotiedosto sijaitsee samassa hakemistossa kuin päätiedostoni ja otsikkotiedostoni (nykyinen työhakemisto). Tarkkaile seuraavaa kuvaa:

Komento export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH päivittää ympäristömuuttujan $LD_LIBRARY_PATH merkinnällä .:, joka ilmaisee, että järjestelmän pitäisi hakea kirjastotietokannat senhetkisestä työhakemistosta. Komento export tekee tästä muutoksesta globaalin, jotta mikä tahansa komentotulkki voi käyttää samaa arvoa. Näin ollen, kun kaikuin muuttujaan, näen päivitykseni. Kun suoritan ldd len uudelleen, näen, että libholberton.so on osoitteessa 0x00007fb9216b9000, joka on todennäköisesti sen sijainti nykyisessä työhakemistossa muistissa. Näin ollen suoritettavan ohjelman riippuvuus jaetusta kirjastosta täyttyy nyt ja ohjelma palauttaa 9, joka on sanan ”Holberton” pituus.

Vastaa

Sähköpostiosoitettasi ei julkaista.