I computere skal en proces placeres i hukommelsen for at kunne eksekveres. Til dette skal et felt tildeles en proces i hukommelsen. Hukommelseallokering er et vigtigt spørgsmål at være opmærksom på, især i kerne- og systemarkitekturer.

Lad os tage et kig på Linux-hukommelsesallokering i detaljer og forstå, hvad der foregår bag kulisserne.

Hvordan foregår hukommelsestildeling?

De fleste softwareingeniører kender ikke detaljerne i denne proces. Men hvis du er systemprogrammørkandidat, bør du vide mere om det. Når man ser på allokeringsprocessen, er det nødvendigt at gå lidt i detaljer om Linux og glibc bibliotek.

Når programmer har brug for hukommelse, skal de anmode om det fra operativsystemet. Denne anmodning fra kernen vil naturligvis kræve et systemkald. Du kan ikke selv tildele hukommelse i brugertilstand.

Det malloc() familie af funktioner er ansvarlig for hukommelsesallokering i C-sproget. Spørgsmålet, der skal stilles her, er, om malloc(), som en glibc-funktion, foretager et direkte systemkald.

instagram viewer

Der er intet systemkald kaldet malloc i Linux-kernen. Der er dog to systemkald til applikationshukommelseskrav, som er brk og mmap.

Da du vil anmode om hukommelse i din applikation via glibc-funktioner, undrer du dig måske over, hvilke af disse systemkald glibc bruger på dette tidspunkt. Svaret er begge dele.

Det første systemkald: brk

Hver proces har et sammenhængende datafelt. Med brk-systemkaldet øges programpauseværdien, som bestemmer grænsen for datafeltet, og allokeringsprocessen udføres.

Selvom hukommelsesallokering med denne metode er meget hurtig, er det ikke altid muligt at returnere ubrugt plads til systemet.

Overvej f.eks., at du tildeler fem felter, hver 16KB i størrelse, med brk-systemkaldet via malloc()-funktionen. Når du er færdig med nummer to af disse felter, er det ikke muligt at returnere den relevante ressource (deallokering), så systemet kan bruge den. For hvis du reducerer adresseværdien for at vise det sted, hvor dit felt nummer to starter, med et opkald til brk, har du foretaget deallokering for felt nummer tre, fire og fem.

For at forhindre tab af hukommelse i dette scenarie overvåger malloc-implementeringen i glibc de tildelte pladser i procesdatafeltet og specificerer derefter at returnere det til systemet med free()-funktionen, så systemet kan bruge den ledige plads til yderligere hukommelse tildelinger.

Med andre ord, efter at fem 16KB områder er allokeret, hvis det andet område returneres med funktionen free() og et andet 16KB område anmodes igen efter et stykke tid, i stedet for at forstørre dataområdet gennem brk-systemkaldet, returneres den tidligere adresse.

Men hvis det nyligt anmodede område er større end 16KB, så vil dataområdet blive forstørret ved at allokere et nyt område med brk-systemkaldet, da område to ikke kan bruges. Selvom område nummer to ikke er i brug, kan applikationen ikke bruge det på grund af størrelsesforskellen. På grund af scenarier som dette er der en situation, der kaldes intern fragmentering, og faktisk kan du sjældent bruge alle dele af hukommelsen fuldt ud.

For bedre forståelse kan du prøve at kompilere og køre følgende eksempelapplikation:

#omfatte <stdio.h>
#omfatte <stdlib.h>
#omfatte <unistd.h>
intvigtigste(int argc, char* argv[])
{
char *ptr[7];
int n;
printf("Pid på %s: %d", argv[0], getpid());
printf("Indledende programpause: %p", sbrk (0));
for (n=0; n<5; n++) ptr[n] = malloc (16 * 1024);
printf("Efter 5 x 16kB malloc: %p", sbrk (0));
ledig(ptr[1]);
printf("Efter fri for anden 16kB: %p", sbrk (0));
ptr[5] = malloc (16 * 1024);
printf("Efter tildeling af 6. af 16kB: %p", sbrk (0));
ledig(ptr[5]);
printf("Efter frigørelse af sidste blok: %p", sbrk (0));
ptr[6] = malloc (18 * 1024);
printf("Efter tildeling af en ny 18kB: %p", sbrk (0));
getchar();
Vend tilbage0;
}

Når du kører programmet, får du et resultat, der ligner følgende output:

Pid af ./a.out: 31990
Indledende program pause: 0x55ebcadf4000
Efter 5 x 16kB malloc: 0x55ebcadf4000
Efter fri for anden 16kB: 0x55ebcadf4000
Efter tildeling af 6. af 16 kB: 0x55ebcadf4000
Efter frigørelse af sidste blok: 0x55ebcadf4000
Efter tildeling af en ny18kB: 0x55ebcadf4000

Outputtet for brk med strace vil være som følger:

brk(NUL) = 0x5608595b6000
brk (0x5608595d7000) = 0x5608595d7000

Som du kan se, 0x21000 er blevet tilføjet til slutadressen for datafeltet. Du kan forstå dette ud fra værdien 0x5608595d7000. Altså cirka 0x21000, eller 132 KB hukommelse blev tildelt.

Der er to vigtige punkter at overveje her. Den første er tildelingen af ​​mere end det beløb, der er angivet i prøvekoden. En anden er, hvilken kodelinje der forårsagede brk-kaldet, der leverede tildelingen.

Address Space Layout Randomisering: ASLR

Når du kører ovenstående eksempelapplikation efter hinanden, vil du se forskellige adresseværdier hver gang. At få adresserummet til at ændre sig tilfældigt på denne måde komplicerer arbejdet betydeligt sikkerhedsangreb og øger softwaresikkerheden.

Men i 32-bit arkitekturer bruges otte bit generelt til at randomisere adresserummet. At øge antallet af bits vil ikke være passende, da det adresserbare område over de resterende bit vil være meget lavt. Brugen af ​​kun 8-bit kombinationer gør heller ikke tingene vanskelige nok for angriberen.

I 64-bit arkitekturer på den anden side, da der er for mange bits, der kan allokeres til ASLR-drift, er der givet meget større tilfældighed, og graden af ​​sikkerhed øges.

Linux-kernen driver også Android-baserede enheder og ASLR-funktionen er fuldt aktiveret på Android 4.0.3 og nyere. Selv af denne grund alene ville det ikke være forkert at sige, at en 64-bit smartphone giver en betydelig sikkerhedsfordel i forhold til 32-bit versioner.

Ved midlertidigt at deaktivere ASLR-funktionen med følgende kommando, vil det se ud til, at den forrige testapplikation returnerer de samme adresseværdier, hver gang den køres:

ekko0 | sudo tee /proc/sys/kernel/randomize_va_space

For at gendanne den til sin tidligere tilstand vil det være nok at skrive 2 i stedet for 0 i den samme fil.

Det andet systemkald: mmap

mmap er det andet systemkald, der bruges til hukommelsesallokering på Linux. Med mmap-opkaldet er den ledige plads i ethvert område af hukommelsen afbildet til adresserummet for opkaldsprocessen.

I en hukommelsesallokering udført på denne måde, når du ønsker at returnere den anden 16KB partition med free()-funktionen i det forrige brk-eksempel, er der ingen mekanisme til at forhindre denne operation. Det relevante hukommelsessegment fjernes fra processens adresseområde. Den er markeret som ikke længere brugt og returneres til systemet.

Fordi hukommelsestildelinger med mmap er meget langsomme sammenlignet med dem med brk, er brk-allokering nødvendig.

Med mmap er ethvert ledigt hukommelsesområde afbildet til processens adresserum, så indholdet af den tildelte plads nulstilles, før denne proces er fuldført. Hvis nulstillingen ikke blev udført på denne måde, kunne dataene tilhørende processen, der tidligere brugte det relevante hukommelsesområde, også tilgås af den næste ikke-relaterede proces. Dette ville gøre det umuligt at tale om sikkerhed i systemer.

Vigtigheden af ​​hukommelsesallokering i Linux

Hukommelseallokering er meget vigtig, især i optimerings- og sikkerhedsspørgsmål. Som det ses i eksemplerne ovenfor, kan en ikke helt forståelse af dette problem betyde, at dit systems sikkerhed ødelægges.

Selv koncepter, der ligner push og pop, der findes i mange programmeringssprog, er baseret på hukommelsesallokeringsoperationer. At kunne bruge og mestre systemhukommelsen godt er afgørende både i indlejret systemprogrammering og i udviklingen af ​​en sikker og optimeret systemarkitektur.

Hvis du også vil dyppe tæerne i Linux-kerneudvikling, så overvej først at mestre C-programmeringssproget.

En kort introduktion til programmeringssproget C

Læs Næste

DelTweetDelE-mail

Relaterede emner

  • Linux
  • Computerhukommelse
  • Linux-kerne

Om forfatteren

Fatih Küçükkarakurt (7 artikler udgivet)

En ingeniør og softwareudvikler, der er fan af matematik og teknologi. Han har altid godt kunne lide computere, matematik og fysik. Han har udviklet spilmotorprojekter samt maskinlæring, kunstige neurale netværk og lineære algebrabiblioteker. Arbejder desuden med maskinlæring og lineære matricer.

Mere fra Fatih Küçükkarakurt

Abonner på vores nyhedsbrev

Tilmeld dig vores nyhedsbrev for tekniske tips, anmeldelser, gratis e-bøger og eksklusive tilbud!

Klik her for at abonnere