Kompiuteriuose, kad procesas būtų vykdomas, jis turi būti įdėtas į atmintį. Tam atmintyje procesui turi būti priskirtas laukas. Atminties paskirstymas yra svarbi problema, kurią reikia žinoti, ypač branduolio ir sistemos architektūrose.
Pažvelkime į Linux atminties paskirstymą išsamiai ir suprasime, kas vyksta užkulisiuose.
Kaip atliekamas atminties paskirstymas?
Dauguma programinės įrangos inžinierių nežino šio proceso detalių. Bet jei esate sistemos programuotojo kandidatas, turėtumėte apie tai daugiau sužinoti. Žvelgiant į paskirstymo procesą, būtina šiek tiek įsigilinti į „Linux“ ir „ glibc biblioteka.
Kai programoms reikia atminties, jos turi paprašyti jos iš operacinės sistemos. Šiai užklausai iš branduolio, žinoma, reikės sistemos iškvietimo. Vartotojo režimu negalite patys skirti atminties.
The malloc () funkcijų šeima yra atsakinga už atminties paskirstymą C kalba. Čia reikia užduoti klausimą, ar malloc(), kaip glibc funkcija, atlieka tiesioginį sistemos iškvietimą.
„Linux“ branduolyje nėra sistemos skambučio, vadinamo malloc. Tačiau yra du sistemos iškvietimai dėl programų atminties poreikių, kurie yra
brk ir mmap.Kadangi prašysite atminties programoje naudodami glibc funkcijas, jums gali kilti klausimas, kurį iš šių sistemos skambučių glibc naudoja šiuo metu. Atsakymas yra abu.
Pirmasis sistemos skambutis: brk
Kiekvienas procesas turi gretimą duomenų lauką. Su brk sistemos iškvietimu padidinama programos pertraukos reikšmė, kuri lemia duomenų lauko ribą ir atliekamas paskirstymo procesas.
Nors atminties paskirstymas šiuo metodu yra labai greitas, ne visada įmanoma grąžinti nepanaudotą erdvę į sistemą.
Pavyzdžiui, brk sistemos iškvietimui per funkciją malloc() priskiriate penkis laukus, kurių kiekvienas yra 16 KB. Kai baigsite su dviem iš šių laukų, nebus įmanoma grąžinti atitinkamo resurso (paskirstymo), kad sistema galėtų jį naudoti. Nes jei sumažinsite adreso reikšmę, kad parodytumėte vietą, kur prasideda jūsų antrasis laukas, skambindami į brk, atliksite trečiojo, ketvirto ir penkto laukų paskirstymą.
Siekiant išvengti atminties praradimo pagal šį scenarijų, malloc diegimas glibc stebi proceso duomenų lauke skirtas vietas ir tada nurodo grąžinti jį į sistemą su funkcija free(), kad sistema galėtų panaudoti laisvą vietą tolesnei atminčiai asignavimų.
Kitaip tariant, po penkių skiriamos 16KB sritys, jei antroji sritis grąžinama su free() funkcija ir dar 16KB sritis po kurio laiko vėl prašoma, užuot padidinus duomenų sritį per brk sistemos iškvietimą, grąžinamas ankstesnis adresas.
Tačiau jei naujai prašoma sritis yra didesnė nei 16 KB, duomenų sritis bus padidinta priskiriant naują sritį su brk sistemos iškvietimu, nes antroji sritis negali būti naudojama. Nors antroji sritis nenaudojama, programa negali jos naudoti dėl dydžio skirtumo. Dėl tokių scenarijų susidaro situacija, vadinama vidiniu susiskaidymu, ir iš tikrųjų retai galite iki galo išnaudoti visas atminties dalis.
Norėdami geriau suprasti, pabandykite sukompiliuoti ir paleisti šią pavyzdinę programą:
#įtraukti <stdio.h>
#įtraukti <stdlib.h>
#įtraukti <unistd.h>
tarptpagrindinis(tarpt argc, char* argv[])
{
char *ptr[7];
tarpt n;
printf("%s Pid: %d", argv[0], getpid());
printf("Pradinė programos pertrauka: %p", sbrk (0));
už (n=0; n<5; n++) ptr[n] = malloc (16 * 1024);
printf("Po 5 x 16kB malloc: %p", sbrk (0));
Laisvas(ptr[1]);
printf("Atlaisvinus sekundę 16kB: %p", sbrk (0));
ptr[5] = malloc (16 * 1024);
printf("Paskyrus 6 iš 16kB: %p", sbrk (0));
Laisvas(ptr[5]);
printf("Atlaisvinus paskutinį bloką: %p", sbrk (0));
ptr[6] = malloc (18 * 1024);
printf("Paskyrus naują 18kB: %p", sbrk (0));
getchar ();
grąžinti0;
}
Kai paleisite programą, gausite rezultatą, panašų į šią išvestį:
Pid of ./a.out: 31990
Pradinė programa pertrauka: 0x55ebcadf4000
Po 5 x 16 kB malloc: 0x55ebcadf4000
Atlaisvinus antrąjį 16kB: 0x55ebcadf4000
Paskyrus 6 16 kB: 0x55ebcadf4000
Atlaisvinus paskutinį bloką: 0x55ebcadf4000
Paskyrus a naujas18kB: 0x55ebcadf4000
Brk su strace išvestis bus tokia:
brk (NULL) = 0x5608595b6000
brk (0x5608595d7000) = 0x5608595d7000
Kaip matai, 0x21000 buvo pridėtas prie duomenų lauko pabaigos adreso. Tai galite suprasti iš vertės 0x5608595d7000. Taigi maždaug 0x21000, arba buvo skirta 132KB atminties.
Čia reikia atsižvelgti į du svarbius dalykus. Pirmasis yra daugiau nei nurodyta pavyzdiniame kode. Kitas dalykas yra tai, kuri kodo eilutė sukėlė brk skambutį, kuris suteikė paskirstymą.
Adreso erdvės išdėstymo atsitiktinis nustatymas: ASLR
Kai vieną po kitos paleisite aukščiau pateiktą pavyzdinę programą, kiekvieną kartą matysite skirtingas adresų reikšmes. Adreso erdvės pasikeitimas atsitiktinai tokiu būdu labai apsunkina darbą saugumo atakas ir padidina programinės įrangos saugumą.
Tačiau 32 bitų architektūrose adresų erdvei atsitiktinai parinkti paprastai naudojami aštuoni bitai. Padidinti bitų skaičių netiks, nes likusių bitų adresuojama sritis bus labai maža. Be to, tik 8 bitų derinių naudojimas užpuolikui pakankamai neapsunkina.
Kita vertus, 64 bitų architektūrose, kadangi yra per daug bitų, kuriuos galima skirti ASLR veikimui, suteikiamas daug didesnis atsitiktinumas ir padidėja saugumo laipsnis.
„Linux“ branduolys taip pat veikia Android pagrįsti įrenginiai ir ASLR funkcija visiškai suaktyvinta 4.0.3 ir naujesnėse versijose „Android“. Jau vien dėl šios priežasties nebūtų klaidinga teigti, kad 64 bitų išmanusis telefonas suteikia didelį saugumo pranašumą prieš 32 bitų versijas.
Laikinai išjungus ASLR funkciją su šia komanda, atrodys, kad ankstesnė bandomoji programa grąžina tas pačias adreso reikšmes kiekvieną kartą, kai ji vykdoma:
aidas0 | sudo tee /proc/sys/kernel/randomize_va_space
Norint atkurti ankstesnę būseną, tame pačiame faile užteks įrašyti 2, o ne 0.
Antrasis sistemos skambutis: mmap
mmap yra antrasis sistemos skambutis, naudojamas atminties paskirstymui Linux sistemoje. Naudojant mmap skambutį, laisva vieta bet kurioje atminties srityje susieta su skambinimo proceso adreso erdve.
Atminties paskirstymas atliktas tokiu būdu, kai norite grąžinti antrąjį 16 KB skaidinį su funkcija free() ankstesniame brk pavyzdyje, nėra mechanizmo, kuris užkirstų kelią šiai operacijai. Atitinkamas atminties segmentas pašalinamas iš proceso adresų erdvės. Jis pažymimas kaip nebenaudojamas ir grąžinamas į sistemą.
Kadangi atminties paskirstymas naudojant mmap yra labai lėtas, palyginti su brk, reikalingas brk paskirstymas.
Naudojant mmap, bet kuri laisva atminties sritis susieta su proceso adresų erdve, todėl paskirstytos vietos turinys nustatomas iš naujo, kol šis procesas nesibaigia. Jei atstatymas nebuvo atliktas tokiu būdu, duomenis, priklausančius procesui, kuris anksčiau naudojo atitinkamą atminties sritį, taip pat galėtų pasiekti kitas nesusijęs procesas. Dėl to būtų neįmanoma kalbėti apie sistemų saugumą.
Atminties paskirstymo svarba Linux sistemoje
Atminties paskirstymas yra labai svarbus, ypač optimizavimo ir saugumo klausimais. Kaip matyti iš pirmiau pateiktų pavyzdžių, visiškai nesuprasdami šios problemos, galite sunaikinti sistemos saugumą.
Netgi koncepcijos, panašios į push ir pop, egzistuojančios daugelyje programavimo kalbų, yra pagrįstos atminties paskirstymo operacijomis. Gebėjimas naudoti ir valdyti sistemos atmintį yra gyvybiškai svarbus tiek programuojant įterptąją sistemą, tiek kuriant saugią ir optimizuotą sistemos architektūrą.
Jei taip pat norite pasinerti į Linux branduolio kūrimą, pirmiausia apsvarstykite galimybę išmokti C programavimo kalbą.
Trumpas C programavimo kalbos įvadas
Skaitykite toliau
Susijusios temos
- Linux
- Kompiuterio atmintis
- Linux branduolys
Apie autorių
Inžinierius ir programinės įrangos kūrėjas, kuris yra matematikos ir technologijų gerbėjas. Jam visada patiko kompiuteriai, matematika ir fizika. Jis sukūrė žaidimų variklių projektus, taip pat mašininį mokymąsi, dirbtinius neuroninius tinklus ir tiesinės algebros bibliotekas. Be to, toliau dirba su mašininiu mokymusi ir tiesinėmis matricomis.
Prenumeruokite mūsų naujienlaiškį
Prisijunkite prie mūsų naujienlaiškio, kad gautumėte techninių patarimų, apžvalgų, nemokamų el. knygų ir išskirtinių pasiūlymų!
Spauskite čia norėdami užsiprenumeruoti