I datorer, för att en process ska vara körbar, måste den placeras i minnet. För detta måste ett fält tilldelas en process i minnet. Minnesallokering är en viktig fråga att vara medveten om, särskilt i kärn- och systemarkitekturer.

Låt oss ta en titt på Linux minnesallokering i detalj och förstå vad som händer bakom kulisserna.

Hur går minnesallokering till?

De flesta mjukvaruingenjörer känner inte till detaljerna i denna process. Men om du är en systemprogrammerareskandidat bör du veta mer om det. När man tittar på allokeringsprocessen är det nödvändigt att gå in lite i detalj på Linux och glibc bibliotek.

När applikationer behöver minne måste de begära det från operativsystemet. Denna begäran från kärnan kommer naturligtvis att kräva ett systemanrop. Du kan inte tilldela minne själv i användarläge.

De malloc() familj av funktioner ansvarar för minnesallokering i C-språket. Frågan att ställa här är om malloc(), som en glibc-funktion, gör ett direkt systemanrop.

Det finns inget systemanrop som heter malloc i Linux-kärnan. Det finns dock två systemanrop för applikationsminneskrav, vilka är

instagram viewer
brk och mmap.

Eftersom du kommer att begära minne i din applikation via glibc-funktioner, kanske du undrar vilket av dessa systemanrop glibc använder vid det här laget. Svaret är både och.

Det första systemanropet: brk

Varje process har ett sammanhängande datafält. Med brk-systemanropet ökas programavbrottsvärdet, som bestämmer gränsen för datafältet, och allokeringsprocessen utförs.

Även om minnesallokering med denna metod är mycket snabb, är det inte alltid möjligt att returnera oanvänt utrymme till systemet.

Tänk till exempel att du allokerar fem fält, vart och ett på 16KB i storlek, med brk-systemanropet via malloc()-funktionen. När du är klar med nummer två av dessa fält är det inte möjligt att returnera den aktuella resursen (deallokering) så att systemet kan använda den. För om du minskar adressvärdet för att visa platsen där ditt fält nummer två börjar, med ett anrop till brk, har du gjort omallokering för fält nummer tre, fyra och fem.

För att förhindra minnesförlust i detta scenario övervakar malloc-implementeringen i glibc de platser som tilldelats i processdatafältet och anger sedan att returnera det till systemet med funktionen free() så att systemet kan använda det lediga utrymmet för ytterligare minne anslag.

Med andra ord, efter att fem 16KB-områden har allokerats, om det andra området returneras med funktionen free() och ytterligare ett 16KB-område efterfrågas igen efter ett tag, istället för att förstora dataområdet genom brk-systemanropet, returneras den tidigare adressen.

Emellertid, om det nyligen begärda området är större än 16KB, kommer dataområdet att förstoras genom att tilldela ett nytt område med brk-systemanropet eftersom område två inte kan användas. Även om område nummer två inte används kan programmet inte använda det på grund av storleksskillnaden. På grund av sådana här scenarier finns det en situation som kallas intern fragmentering, och i själva verket kan du sällan använda alla delar av minnet till fullo.

För bättre förståelse, försök att kompilera och köra följande exempelapplikation:

#omfatta <stdio.h>
#omfatta <stdlib.h>
#omfatta <unistd.h>
inthuvud(int argc, röding* argv[])
{
röding *ptr[7];
int n;
printf("Pid på %s: %d", argv[0], getpid());
printf("Inledande programavbrott: %p"sbrk (0));
för (n=0; n<5; n++) ptr[n] = malloc (16 * 1024);
printf("Efter 5 x 16kB malloc: %p"sbrk (0));
fri(ptr[1]);
printf("Efter fri från andra 16kB: %p"sbrk (0));
ptr[5] = malloc (16 * 1024);
printf("Efter tilldelning av 6:e av 16kB: %p"sbrk (0));
fri(ptr[5]);
printf("Efter frigöring av sista blocket: %p"sbrk (0));
ptr[6] = malloc (18 * 1024);
printf("Efter tilldelning av en ny 18kB: %p"sbrk (0));
getchar();
lämna tillbaka0;
}

När du kör programmet får du ett resultat som liknar följande utdata:

Pid av ./a.out: 31990
Inledande program ha sönder: 0x55ebcadf4000
Efter 5 x 16kB malloc: 0x55ebcadf4000
Efter fri från andra 16kB: 0x55ebcadf4000
Efter tilldelning av 6:e av 16kB: 0x55ebcadf4000
Efter att det sista blocket frigjorts: 0x55ebcadf4000
Efter att ha tilldelats en ny18kB: 0x55ebcadf4000

Utdata för brk med strace blir som följer:

brk(NULL) = 0x5608595b6000
brk (0x5608595d7000) = 0x5608595d7000

Som du kan se, 0x21000 har lagts till i slutadressen för datafältet. Du kan förstå detta av värdet 0x5608595d7000. Så ungefär 0x21000, eller 132KB minne tilldelades.

Det finns två viktiga punkter att ta hänsyn till här. Den första är tilldelningen av mer än det belopp som anges i exempelkoden. En annan är vilken kodrad som orsakade brk-anropet som gav tilldelningen.

Adressutrymmeslayout Randomisering: ASLR

När du kör exemplet ovan efter varandra, ser du olika adressvärden varje gång. Att ändra adressutrymmet slumpmässigt på detta sätt komplicerar arbetet avsevärt säkerhetsattacker och ökar mjukvarusäkerheten.

Men i 32-bitars arkitekturer används vanligtvis åtta bitar för att slumpmässigt göra adressutrymmet. Att öka antalet bitar kommer inte att vara lämpligt eftersom det adresserbara området över de återstående bitarna kommer att vara mycket lågt. Dessutom gör användningen av endast 8-bitars kombinationer inte det svårt nog för angriparen.

I 64-bitars arkitekturer å andra sidan, eftersom det finns för många bitar som kan allokeras för ASLR-drift, tillhandahålls mycket större slumpmässighet, och graden av säkerhet ökar.

Linux-kärnan driver också Android-baserade enheter och ASLR-funktionen är helt aktiverad på Android 4.0.3 och senare. Även av detta skäl skulle det inte vara fel att säga att en 64-bitars smartphone ger en betydande säkerhetsfördel jämfört med 32-bitarsversioner.

Genom att tillfälligt inaktivera ASLR-funktionen med följande kommando, kommer det att verka som att den tidigare testapplikationen returnerar samma adressvärden varje gång den körs:

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

För att återställa den till dess tidigare tillstånd räcker det att skriva 2 istället för 0 i samma fil.

Det andra systemanropet: mmap

mmap är det andra systemanropet som används för minnesallokering på Linux. Med mmap-anropet mappas det lediga utrymmet i valfritt område av minnet till adressutrymmet för anropsprocessen.

I en minnesallokering gjord på detta sätt, när du vill returnera den andra 16KB-partitionen med funktionen free() i föregående brk-exempel, finns det ingen mekanism för att förhindra denna operation. Det relevanta minnessegmentet tas bort från processens adressutrymme. Den är markerad som inte längre använd och returneras till systemet.

Eftersom minnesallokering med mmap är mycket långsam jämfört med de med brk, behövs brk-allokering.

Med mmap mappas alla lediga minnesområden till processens adressutrymme, så innehållet i det tilldelade utrymmet återställs innan denna process är klar. Om återställningen inte gjordes på detta sätt kunde data som hör till processen som tidigare använde det relevanta minnesområdet också nås av nästa orelaterade process. Detta skulle göra det omöjligt att prata om säkerhet i system.

Vikten av minnesallokering i Linux

Minnesallokering är mycket viktig, särskilt i optimerings- och säkerhetsfrågor. Som framgår av exemplen ovan kan det innebära att systemets säkerhet förstörs om du inte förstår problemet helt.

Även koncept som liknar push och pop som finns i många programmeringsspråk är baserade på minnesallokeringsoperationer. Att kunna använda och bemästra systemminnet väl är avgörande både vid programmering av inbyggda system och för att utveckla en säker och optimerad systemarkitektur.

Om du också vill doppa tårna i Linux-kärnutveckling, överväg att behärska programmeringsspråket C först.

En kort introduktion till programmeringsspråket C

Läs Nästa

Dela med sigTweetDela med sigE-post

Relaterade ämnen

  • Linux
  • Datorminne
  • Linux kärna

Om författaren

Fatih Küçükkarakurt (7 publicerade artiklar)

En ingenjör och mjukvaruutvecklare som är ett fan av matematik och teknik. Han har alltid gillat datorer, matematik och fysik. Han har utvecklat spelmotorprojekt samt maskininlärning, artificiella neurala nätverk och linjära algebrabibliotek. Fortsätter dessutom att arbeta med maskininlärning och linjära matriser.

Mer från Fatih Küçükkarakurt

Prenumerera på vårt nyhetsbrev

Gå med i vårt nyhetsbrev för tekniska tips, recensioner, gratis e-böcker och exklusiva erbjudanden!

Klicka här för att prenumerera