Gebruik Linux’s ar
opdracht om functiebibliotheken te maken wanneer u software ontwikkelt. Deze tutorial laat je zien hoe je een statische bibliotheek maakt, deze aanpast en gebruikt in een programma, compleet met voorbeeldcode.
De ar
command is een echte veteraan – het bestaat al sinds 1971. De naam ar
verwijst naar het oorspronkelijke beoogde gebruik van de tool, namelijk het maken van archiefbestanden. Een archiefbestand is een enkel bestand dat fungeert als een container voor andere bestanden. Soms voor veel andere bestanden. Bestanden kunnen worden toegevoegd aan, verwijderd uit of geëxtraheerd uit het archief. Mensen die op zoek zijn naar dat soort functionaliteit, gaan niet meer naar ar
. Die rol is overgenomen door andere nutsbedrijven zoals tar
.
De ar
commando wordt echter nog steeds gebruikt voor een paar specialistische doeleinden. ar
wordt gebruikt om statische bibliotheken te maken. Deze worden gebruikt bij softwareontwikkeling. En ar
wordt ook gebruikt om pakketbestanden te maken zoals de “.deb” -bestanden die worden gebruikt in de Debian Linux-distributie en zijn afgeleiden zoals Ubuntu.
We gaan de stappen doorlopen die nodig zijn om een statische bibliotheek te maken en te wijzigen, en laten zien hoe u de bibliotheek in een programma kunt gebruiken. Om dat te doen, hebben we een vereiste nodig waaraan de statische bibliotheek moet voldoen. Het doel van deze bibliotheek is om tekstreeksen te coderen en gecodeerde tekst te decoderen.
Let op, dit is een snelle en vuile hack voor demonstratiedoeleinden. Gebruik deze codering niet voor iets dat van waarde is. Het is ’s werelds eenvoudigste vervangingscijfer, waarbij A B wordt, B C wordt, enzovoort.
VERWANT: Bestanden comprimeren en extraheren met de tar-opdracht op Linux
De cipher_encode () en cipher_decode () functies
We gaan werken in een map met de naam ‘bibliotheek’ en later maken we een submap met de naam ’test’.
We hebben twee bestanden in deze map. In een tekstbestand met de naam cipher_encode.c hebben we de cipher_encode()
functie:
void cipher_encode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]++; } } // end of cipher_encode
De bijbehorende cipher_decode()
functie is in een tekstbestand genaamd cipher_decode.c:
void cipher_decode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]--; } } // end of cipher_decode
Bestanden die programmeerinstructies bevatten, worden broncodebestanden genoemd. We gaan een bibliotheekbestand maken met de naam libcipher.a. Het bevat de gecompileerde versies van deze twee broncodebestanden. We zullen ook een kort tekstbestand maken met de naam libcipher.h. Dit is een header-bestand met de definities van de twee functies in onze nieuwe bibliotheek.
Iedereen met de bibliotheek en het header-bestand kan de twee functies in hun eigen programma’s gebruiken. Ze hoeven het wiel niet opnieuw uit te vinden en de functies opnieuw te schrijven; ze maken gewoon gebruik van de exemplaren in onze bibliotheek.
Het compileren van de cipher_encode.c en cipher_decode.c bestanden
Om de broncodebestanden te compileren, zullen we gcc
, de standaard GNU-compiler. De -c
(compileren, geen link) optie vertelt gcc
om de bestanden te compileren en vervolgens te stoppen. Het produceert een tussenbestand van elk broncodebestand dat een objectbestand wordt genoemd. De gcc
linker neemt meestal alle objectbestanden en koppelt ze aan elkaar om een uitvoerbaar programma te maken. We slaan die stap over door de -c
optie. We hebben alleen de objectbestanden nodig.
Laten we eens kijken of we de bestanden hebben waarvan we denken dat we ze hebben.
ls -l
De twee broncodebestanden zijn aanwezig in deze directory. Laten we gebruiken gcc
om ze te compileren tot objectbestanden.
gcc -c cipher_encode.c
gcc -c cipher_decode.c
Er mag geen uitvoer zijn van gcc
als alles goed gaat.
Dit genereert twee objectbestanden met dezelfde naam als de broncodebestanden, maar met de extensie “.o”. Dit zijn de bestanden die we aan het bibliotheekbestand moeten toevoegen.
ls -l
De libcipher.a-bibliotheek maken
Om het bibliotheekbestand te maken – dat eigenlijk een archiefbestand is – zullen we gebruiken ar
.
We gebruiken de -c
(create) optie om het bibliotheekbestand, de -r
(toevoegen met vervangen) optie om de bestanden aan het bibliotheekbestand toe te voegen, en de -s
(index) optie om een index van de bestanden in het bibliotheekbestand te maken.
We gaan het bibliotheekbestand libcipher.a noemen. We geven die naam op de opdrachtregel, samen met de namen van de objectbestanden die we aan de bibliotheek gaan toevoegen.
ar -crs libcipher.a cipher_encode.o cipher_decode.o
Als we de bestanden in de directory vermelden, zullen we zien dat we nu een libcipher.a-bestand hebben.
ls -l
Als we de -t
(tafel) optie met ar
we kunnen de modules in het bibliotheekbestand zien.
ar -t libcipher.a
Het libcipher.h-headerbestand maken
Het bestand libcipher.h wordt opgenomen in elk programma dat de bibliotheek libcipher.a gebruikt. Het bestand libcipher.h moet de definitie bevatten van de functies die in de bibliotheek staan.
Om het header-bestand te maken, moeten we de functiedefinities typen in een teksteditor zoals gedit. Noem het bestand “libcipher.h” en sla het op in dezelfde directory als het bestand libcipher.a.
void cipher_encode(char *text); void cipher_decode(char *text);
Met behulp van de libcipher-bibliotheek
De enige zekere manier om onze nieuwe bibliotheek te testen, is door een klein programma te schrijven om het te gebruiken. Eerst maken we een map met de naam test.
mkdir test
We kopiëren de bibliotheek- en headerbestanden naar de nieuwe map.
cp libcipher.* ./test
We gaan naar de nieuwe directory.
cd test
Laten we eens kijken of onze twee bestanden hier zijn.
ls -l
We moeten een klein programma maken dat de bibliotheek kan gebruiken en kan bewijzen dat het naar verwachting functioneert. Typ de volgende regels tekst in een editor. Sla de inhoud van de editor op in een bestand met de naam “test.c” in het test directory.
#include <stdio.h> #include <stdlib.h> #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="How-To Geek loves Linux"; puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // end of main
Het programmaverloop is heel eenvoudig:
- Het bevat het bestand libcipher.h zodat het de definities van bibliotheekfuncties kan zien.
- Het maakt een string met de naam “text” en slaat de woorden “How-To Geek loves Linux” erin op.
- Het drukt die string af op het scherm.
- het roept de
cipher_encode()
functie om de string te coderen, en het print de gecodeerde string naar het scherm. - Het roept
cipher_decode()
om de string te decoderen en de gedecodeerde string op het scherm af te drukken.
Om het test
programma, moeten we het test.c programma compileren en koppelen in de bibliotheek. De -o
(output) optie vertelt gcc
hoe het uitvoerbare programma dat het genereert te noemen.
gcc test.c libcipher.a -o test
Als gcc
keert u stilletjes terug naar de opdrachtprompt, alles is goed. Laten we nu ons programma testen. Moment van de waarheid:
./test
En we zien de verwachte output. De test
programma drukt de platte tekst af, drukt de gecodeerde tekst af en drukt vervolgens de gedecodeerde tekst af. Het maakt gebruik van de functies in onze nieuwe bibliotheek. Onze bibliotheek werkt.
Succes. Maar waarom zou je daar stoppen?
Een andere module aan de bibliotheek toevoegen
Laten we nog een functie aan de bibliotheek toevoegen. We zullen een functie toevoegen die de programmeur kan gebruiken om de versie van de bibliotheek die ze gebruiken weer te geven. We zullen de nieuwe functie moeten maken, deze moeten compileren en het nieuwe objectbestand aan het bestaande bibliotheekbestand moeten toevoegen.
Typ de volgende regels in een editor. Sla de inhoud van de editor op in een bestand met de naam cipher_version.c, in het bibliotheek directory.
#include <stdio.h> void cipher_version(void) { puts("How-To Geek :: VERY INSECURE Cipher Library"); puts("Version 0.0.1 Alphan"); } // end of cipher_version
We moeten de definitie van de nieuwe functie toevoegen aan het libcipher.h-headerbestand. Voeg een nieuwe regel toe aan de onderkant van dat bestand, zodat het er als volgt uitziet:
void cipher_encode(char *text); void cipher_decode(char *text); void cipher_version(void);
Sla het gewijzigde bestand libcipher.h op.
We moeten het bestand cipher_version.c compileren zodat we een objectbestand cipher_version.o hebben.
gcc -c cipher_version.c
Dit creëert een cipher_version.o-bestand. We kunnen het nieuwe objectbestand toevoegen aan de libcipher.a-bibliotheek met het volgende commando. De -v
(uitgebreide) optie maakt het meestal stil ar
vertel ons wat het heeft gedaan.
ar -rsv libcipher.a cipher_version.o
Het nieuwe objectbestand wordt toegevoegd aan het bibliotheekbestand. ar
drukt een bevestiging af. De “a” betekent “toegevoegd”.
We kunnen de -t
(table) optie om te zien welke modules er in het bibliotheekbestand zitten.
ar -t libcipher.a
Er zijn nu drie modules in ons bibliotheekbestand. Laten we gebruik maken van de nieuwe functie.
De functie cipher_version () gebruiken.
Laten we de oude bibliotheek en het headerbestand uit de testmap verwijderen, de nieuwe bestanden kopiëren en dan teruggaan naar de testmap.
We zullen de oude versies van de bestanden verwijderen.
rm ./test/libcipher.*
We kopiëren de nieuwe versies naar de testdirectory.
cp libcipher.* ./test
We gaan naar de testdirectory.
cd test
En nu kunnen we het programma test.c aanpassen zodat het de nieuwe bibliotheekfunctie gebruikt.
We moeten een nieuwe regel toevoegen aan het test.c-programma dat aanroept cipher_version()
functie. We plaatsen dit voor de eerste puts(text);
lijn.
#include <stdio.h> #include <stdlib.h> #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="How-To Geek loves Linux"; // new line added here cipher_version(); puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // end of main
Bewaar dit als test. C. We kunnen het nu compileren en testen of de nieuwe functie operationeel is.
gcc test.c libcipher.a -o test
Laten we de nieuwe versie van test
:
De nieuwe functie werkt. We kunnen de versie van de bibliotheek zien aan het begin van de uitvoer van test
.
Maar er kan een probleem zijn.
Een module in de bibliotheek vervangen
Dit is niet de eerste versie van de bibliotheek; het is de tweede. Ons versienummer is onjuist. De eerste versie had nr cipher_version()
functie erin. Deze doet het. Dus dit zou versie “0.0.2” moeten zijn. We moeten het cipher_version()
functie in de bibliotheek met een gecorrigeerde.
Dankbaar, ar
maakt dat heel gemakkelijk te doen.
Laten we eerst het bestand cipher_version.c in het bibliotheek directory. Wijzig de tekst “Versie 0.0.1 Alpha” in “Versie 0.0.2 Alpha”. Het zou er als volgt uit moeten zien:
#include <stdio.h> void cipher_version(void) { puts("How-To Geek :: VERY INSECURE Cipher Library"); puts("Version 0.0.2 Alphan"); } // end of cipher_version
Bewaar dit bestand. We moeten het opnieuw compileren om een nieuw cipher_version.o-objectbestand te maken.
gcc -c cipher_version.c
Nu zullen we vervangen het bestaande cipher_version.o-object in de bibliotheek met onze nieuw gecompileerde versie.
We hebben de -r
(toevoegen met vervangen) optie eerder, om nieuwe modules aan de bibliotheek toe te voegen. Als we het gebruiken met een module die al in de bibliotheek bestaat, ar
vervangt de oude versie door de nieuwe. De -s
(index) optie zal de bibliotheekindex en het -v
(uitgebreide) optie zal maken ar
vertel ons wat het heeft gedaan.
ar -rsv libcipher.a cipher_version.o
Deze keer ar
meldt dat het de cipher_version.o module heeft vervangen. De “r” betekent vervangen.
Met behulp van de bijgewerkte cipher_version () functie
We moeten onze aangepaste bibliotheek gebruiken en controleren of deze werkt.
We zullen de bibliotheekbestanden naar de testdirectory kopiëren.
cp libcipher.* ./test
We gaan naar de testdirectory.
cd ./test
We moeten ons testprogramma opnieuw compileren met onze nieuwe bibliotheek.
gcc test.c libcipher.a -o test
En nu kunnen we ons programma testen.
./test
De output van het testprogramma is wat we hadden verwacht. Het juiste versienummer wordt weergegeven in de versiestring en de coderings- en decoderingsroutines werken.
Modules verwijderen uit een bibliotheek
Het lijkt toch jammer, maar laten we het bestand cipher_version.o uit het bibliotheekbestand verwijderen.
Om dit te doen, gebruiken we de -d
(delete) optie. We gebruiken ook de -v
(uitgebreide) optie, zodat ar
vertelt ons wat het heeft gedaan. We nemen ook de -s
(index) optie om de index in het bibliotheekbestand bij te werken.
ar -dsv libcipher.a cipher_version.o
ar
meldt dat het de module heeft verwijderd. De “d” betekent “verwijderd”.
Als we erom vragen ar
om de modules in het bibliotheekbestand weer te geven, zullen we zien dat we terug zijn bij twee modules.
ar -t libcipher.a
Als u modules uit uw bibliotheek gaat verwijderen, vergeet dan niet om hun definitie uit het bibliotheekkopbestand te verwijderen.
Deel uw code
Bibliotheken maken code deelbaar op een praktische maar persoonlijke manier. Iedereen aan wie u het bibliotheekbestand en het headerbestand geeft, kan uw bibliotheek gebruiken, maar uw daadwerkelijke broncode blijft privé.