På datamaskiner, for at en prosess skal være kjørbar, må den plasseres i minnet. For dette må et felt tilordnes en prosess i minnet. Minneallokering er en viktig sak å være klar over, spesielt i kjerne- og systemarkitekturer.

La oss ta en titt på Linux minneallokering i detalj og forstå hva som foregår bak kulissene.

Hvordan gjøres minnetildeling?

De fleste programvareingeniører kjenner ikke detaljene i denne prosessen. Men hvis du er en systemprogrammererkandidat, bør du vite mer om det. Når du ser på allokeringsprosessen, er det nødvendig å gå i detalj på Linux og glibc bibliotek.

Når applikasjoner trenger minne, må de be om det fra operativsystemet. Denne forespørselen fra kjernen vil naturligvis kreve et systemkall. Du kan ikke tildele minne selv i brukermodus.

De malloc() familie av funksjoner er ansvarlig for minnetildeling i C-språket. Spørsmålet å stille her er om malloc(), som en glibc-funksjon, foretar et direkte systemkall.

Det er ingen systemkall kalt malloc i Linux-kjernen. Imidlertid er det to systemanrop for applikasjonsminnekrav, som er brk og mmap.

instagram viewer

Siden du vil be om minne i applikasjonen din via glibc-funksjoner, lurer du kanskje på hvilke av disse systemanropene glibc bruker på dette tidspunktet. Svaret er begge deler.

Det første systemanropet: brk

Hver prosess har et sammenhengende datafelt. Med brk-systemkallet økes programbruddverdien, som bestemmer grensen for datafeltet, og allokeringsprosessen utføres.

Selv om minnetildeling med denne metoden er veldig rask, er det ikke alltid mulig å returnere ubrukt plass til systemet.

Tenk for eksempel på at du tildeler fem felt, hver 16KB i størrelse, med brk-systemkallet via malloc()-funksjonen. Når du er ferdig med nummer to av disse feltene er det ikke mulig å returnere den aktuelle ressursen (deallokering) slik at systemet kan bruke den. For hvis du reduserer adresseverdien for å vise stedet hvor ditt felt nummer to starter, med et kall til brk, vil du ha gjort deallokering for felt nummer tre, fire og fem.

For å forhindre minnetap i dette scenariet, overvåker malloc-implementeringen i glibc stedene som er tildelt i prosessdatafeltet og spesifiserer deretter å returnere den til systemet med free()-funksjonen, slik at systemet kan bruke ledig plass til ytterligere minne tildelinger.

Med andre ord, etter at fem 16KB-områder er tildelt, hvis det andre området returneres med free()-funksjonen og et annet 16KB-område blir bedt om igjen etter en stund, i stedet for å forstørre dataområdet gjennom brk-systemanropet, returneres den forrige adressen.

Imidlertid, hvis det nylig forespurte området er større enn 16KB, vil dataområdet bli utvidet ved å tildele et nytt område med brk-systemanropet siden område to ikke kan brukes. Selv om område nummer to ikke er i bruk, kan ikke applikasjonen bruke det på grunn av størrelsesforskjellen. På grunn av scenarier som dette er det en situasjon som kalles intern fragmentering, og faktisk kan du sjelden bruke alle deler av minnet til det fulle.

For bedre forståelse, prøv å kompilere og kjøre følgende eksempelapplikasjon:

#inkludere <stdio.h>
#inkludere <stdlib.h>
#inkludere <unistd.h>
inthoved-(int argc, røye* argv[])
{
røye *ptr[7];
int n;
printf("Pid på %s: %d", argv[0], getpid());
printf("Innledende programpause: %p", sbrk (0));
for (n=0; n<5; n++) ptr[n] = malloc (16 * 1024);
printf("Etter 5 x 16kB malloc: %p", sbrk (0));
gratis(ptr[1]);
printf("Etter fri for andre 16kB: %p", sbrk (0));
ptr[5] = malloc (16 * 1024);
printf("Etter tildeling av 6. av 16kB: %p", sbrk (0));
gratis(ptr[5]);
printf("Etter frigjøring av siste blokk: %p", sbrk (0));
ptr[6] = malloc (18 * 1024);
printf("Etter tildeling av en ny 18kB: %p", sbrk (0));
getchar();
komme tilbake0;
}

Når du kjører applikasjonen vil du få et resultat som ligner på følgende utdata:

Pid av ./a.out: 31990
Innledende program gå i stykker: 0x55ebcadf4000
Etter 5 x 16kB malloc: 0x55ebcadf4000
Etter fri for andre 16kB: 0x55ebcadf4000
Etter tildeling av 6. av 16 kB: 0x55ebcadf4000
Etter frigjøring av siste blokk: 0x55ebcadf4000
Etter å ha tildelt en ny18kB: 0x55ebcadf4000

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

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

Som du kan se, 0x21000 er lagt til sluttadressen til datafeltet. Du kan forstå dette fra verdien 0x5608595d7000. Så ca 0x21000, eller 132KB minne ble tildelt.

Det er to viktige punkter å vurdere her. Den første er tildelingen av mer enn beløpet som er spesifisert i prøvekoden. En annen er hvilken kodelinje som forårsaket brk-anropet som ga tildelingen.

Randomisering av adresseromsoppsett: ASLR

Når du kjører eksempelapplikasjonen ovenfor etter hverandre, vil du se forskjellige adresseverdier hver gang. Å få adresseområdet til å endres tilfeldig på denne måten kompliserer arbeidet betydelig sikkerhetsangrep og øker programvaresikkerheten.

I 32-bits arkitekturer brukes imidlertid vanligvis åtte biter for å randomisere adresserommet. Å øke antall biter vil ikke være hensiktsmessig da det adresserbare området over de gjenværende bitene vil være svært lavt. Dessuten gjør ikke bruken av bare 8-bits kombinasjoner ting vanskelig nok for angriperen.

I 64-bits arkitekturer derimot, siden det er for mange biter som kan tildeles for ASLR-drift, gis mye større tilfeldighet, og graden av sikkerhet øker.

Linux-kjernen driver også Android-baserte enheter og ASLR-funksjonen er fullt aktivert på Android 4.0.3 og nyere. Selv av denne grunn alene, ville det ikke være feil å si at en 64-bits smarttelefon gir en betydelig sikkerhetsfordel i forhold til 32-biters versjoner.

Ved å midlertidig deaktivere ASLR-funksjonen med følgende kommando, vil det se ut til at den forrige testapplikasjonen returnerer de samme adresseverdiene hver gang den kjøres:

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

For å gjenopprette den til sin forrige tilstand, vil det være nok å skrive 2 i stedet for 0 i samme fil.

Det andre systemanropet: mmap

mmap er det andre systemkallet som brukes for minneallokering på Linux. Med mmap-anropet tilordnes den ledige plassen i et hvilket som helst område av minnet til adresseområdet til anropsprosessen.

I en minneallokering utført på denne måten, når du ønsker å returnere den andre 16KB-partisjonen med free()-funksjonen i forrige brk-eksempel, er det ingen mekanisme for å forhindre denne operasjonen. Det relevante minnesegmentet fjernes fra prosessens adresserom. Den er merket som ikke lenger brukt og returnert til systemet.

Fordi minnetildelinger med mmap er veldig trege sammenlignet med de med brk, er brk-allokering nødvendig.

Med mmap tilordnes ethvert ledig minneområde til prosessens adresserom, slik at innholdet i den tildelte plassen tilbakestilles før denne prosessen er fullført. Hvis tilbakestillingen ikke ble gjort på denne måten, kunne dataene som tilhører prosessen som tidligere brukte det relevante minneområdet også få tilgang til den neste ikke-relaterte prosessen. Dette ville gjøre det umulig å snakke om sikkerhet i systemer.

Viktigheten av minnetildeling i Linux

Minnetildeling er veldig viktig, spesielt i optimaliserings- og sikkerhetsspørsmål. Som vist i eksemplene ovenfor, kan det å ikke helt forstå dette problemet bety å ødelegge systemets sikkerhet.

Selv konsepter som ligner på push og pop som finnes i mange programmeringsspråk er basert på minneallokeringsoperasjoner. Å kunne bruke og mestre systemminnet godt er avgjørende både i innebygd systemprogrammering og for å utvikle en sikker og optimalisert systemarkitektur.

Hvis du også vil dyppe tærne i Linux-kjerneutvikling, bør du vurdere å mestre C-programmeringsspråket først.

En kort introduksjon til programmeringsspråket C

Les Neste

DelekvitringDeleE-post

Relaterte temaer

  • Linux
  • Datamaskinens minne
  • Linux-kjernen

Om forfatteren

Fatih Küçükkarakurt (7 artikler publisert)

En ingeniør og programvareutvikler som er en fan av matematikk og teknologi. Han har alltid likt datamaskiner, matematikk og fysikk. Han har utviklet spillmotorprosjekter samt maskinlæring, kunstige nevrale nettverk og lineære algebrabiblioteker. Videre fortsetter arbeidet med maskinlæring og lineære matriser.

Mer fra Fatih Küçükkarakurt

Abonner på vårt nyhetsbrev

Bli med i vårt nyhetsbrev for tekniske tips, anmeldelser, gratis e-bøker og eksklusive tilbud!

Klikk her for å abonnere