V počítačoch, aby bol proces spustiteľný, musí byť umiestnený v pamäti. Na tento účel musí byť procesu v pamäti priradené pole. Alokácia pamäte je dôležitá otázka, ktorú si treba uvedomiť, najmä v architektúre jadra a systému.
Pozrime sa na alokáciu pamäte Linuxu podrobne a pochopíme, čo sa deje v zákulisí.
Ako sa vykonáva prideľovanie pamäte?
Väčšina softvérových inžinierov nepozná podrobnosti tohto procesu. Ale ak ste kandidát na systémového programátora, mali by ste o tom vedieť viac. Pri pohľade na proces prideľovania je potrebné ísť trochu do detailov o Linuxe a glibc knižnica.
Keď aplikácie potrebujú pamäť, musia si ju vyžiadať od operačného systému. Táto požiadavka z jadra bude prirodzene vyžadovať systémové volanie. V užívateľskom režime nemôžete prideľovať pamäť sami.
The malloc() rodina funkcií je zodpovedná za prideľovanie pamäte v jazyku C. Tu si treba položiť otázku, či malloc() ako funkcia glibc vykonáva priame systémové volanie.
V jadre Linuxu nie je žiadne systémové volanie s názvom malloc. Existujú však dve systémové volania pre požiadavky na pamäť aplikácií, ktoré sú
brk a mmap.Keďže vo svojej aplikácii budete žiadať pamäť prostredníctvom funkcií glibc, možno vás zaujíma, ktoré z týchto systémových volaní glibc v tomto bode používa. Odpoveď je oboje.
Prvé systémové volanie: brk
Každý proces má súvislé dátové pole. Systémovým volaním brk sa zvýši hodnota prerušenia programu, ktorá určuje limit dátového poľa a vykoná sa proces prideľovania.
Hoci je alokácia pamäte touto metódou veľmi rýchla, nie je vždy možné vrátiť nevyužitý priestor systému.
Predstavte si napríklad, že systémovému volaniu brk pridelíte päť polí, každé s veľkosťou 16 kB, pomocou funkcie malloc(). Keď skončíte s číslom dva z týchto polí, nie je možné vrátiť príslušný zdroj (dealokáciu), aby ho systém mohol použiť. Pretože ak znížite hodnotu adresy tak, aby sa zobrazilo miesto, kde začína vaše pole číslo dva, s volaním na brk, urobíte dealokáciu pre polia číslo tri, štyri a päť.
Aby sa predišlo strate pamäte v tomto scenári, implementácia malloc v glibc monitoruje miesta alokované v poli procesných údajov a potom určí, že sa má vrátiť do systému pomocou funkcie free(), aby systém mohol použiť voľný priestor pre ďalšiu pamäť alokácie.
Inými slovami, po piatich pridelených oblastiach s veľkosťou 16 kB, ak sa druhá oblasť vráti pomocou funkcie free() a ďalšia oblasť s veľkosťou 16 kB sa po chvíli opäť vyžiada, namiesto zväčšenia dátovej oblasti prostredníctvom systémového volania brk sa vráti predchádzajúca adresa.
Ak je však novopožadovaná oblasť väčšia ako 16 KB, oblasť údajov sa zväčší pridelením novej oblasti systémovým volaním brk, pretože oblasť dva nemožno použiť. Hoci oblasť číslo dva nie je využívaná, aplikácia ju nemôže využiť kvôli rozdielu veľkosti. Kvôli scenárom, ako je tento, nastáva situácia nazývaná vnútorná fragmentácia a v skutočnosti len zriedka dokážete využiť všetky časti pamäte naplno.
Pre lepšie pochopenie skúste skompilovať a spustiť nasledujúcu vzorovú aplikáciu:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
intHlavná(int argc, char*argv[])
{
char *ptr[7];
int n;
printf("Pid %s: %d", argv[0], getpid());
printf("Počiatočná prestávka programu: %p", sbrk (0));
pre (n=0; n<5; n++) ptr[n] = malloc (16 x 1024);
printf("Po 5 x 16 kB malloc: %p", sbrk (0));
zadarmo(ptr[1]);
printf("Po uvoľnení druhých 16kB: %p", sbrk (0));
ptr[5] = malloc (16 x 1024);
printf("Po pridelení 6. zo 16 kB: %p", sbrk (0));
zadarmo(ptr[5]);
printf("Po uvoľnení posledného bloku: %p", sbrk (0));
ptr[6] = malloc (18 * 1024);
printf("Po pridelení nových 18kB: %p", sbrk (0));
getchar();
vrátiť0;
}
Po spustení aplikácie získate výsledok podobný nasledujúcemu výstupu:
Číslo ./a.out: 31990
Úvodný program prestávka: 0x55ebcadf4000
Po 5 x 16 kB malloc: 0x55ebcadf4000
Po uvoľnení druhých 16kB: 0x55ebcadf4000
Po pridelení 6. zo 16 kB: 0x55ebcadf4000
Po uvoľnení posledného bloku: 0x55ebcadf4000
Po pridelení a Nový18kB: 0x55ebcadf4000
Výstup pre brk so strace bude takýto:
brk(NULOVÝ) = 0x5608595b6000
brk (0x5608595d7000) = 0x5608595d7000
Ako môžeš vidieť, 0x21000 bola pridaná ku koncovej adrese dátového poľa. Môžete to pochopiť z hodnoty 0x5608595d7000. Takže približne 0x21000alebo bolo pridelených 132 kB pamäte.
Tu je potrebné zvážiť dva dôležité body. Prvým je pridelenie väčšieho množstva, ako je uvedené vo vzorovom kóde. Ďalším je, ktorý riadok kódu spôsobil volanie brk, ktoré poskytlo pridelenie.
Randomizácia rozloženia adresného priestoru: ASLR
Keď spustíte vyššie uvedenú príkladovú aplikáciu jednu po druhej, zakaždým uvidíte iné hodnoty adresy. Náhodná zmena adresného priestoru týmto spôsobom výrazne komplikuje prácu bezpečnostné útoky a zvyšuje bezpečnosť softvéru.
V 32-bitových architektúrach sa však na randomizáciu adresného priestoru vo všeobecnosti používa osem bitov. Zvýšenie počtu bitov nebude vhodné, pretože adresovateľná oblasť nad zostávajúcimi bitmi bude veľmi nízka. Taktiež použitie iba 8-bitových kombinácií útočníkom veci dostatočne nesťažuje.
Na druhej strane v 64-bitových architektúrach, keďže existuje príliš veľa bitov, ktoré je možné alokovať na prevádzku ASLR, poskytuje sa oveľa väčšia náhodnosť a zvyšuje sa stupeň bezpečnosti.
Linuxové jadro tiež poháňa Zariadenia so systémom Android a funkcia ASLR je plne aktivovaná v systéme Android 4.0.3 a novšom. Už len z tohto dôvodu by nebolo nesprávne povedať, že 64-bitový smartfón poskytuje značnú bezpečnostnú výhodu oproti 32-bitovým verziám.
Dočasným vypnutím funkcie ASLR pomocou nasledujúceho príkazu sa ukáže, že predchádzajúca testovacia aplikácia vracia rovnaké hodnoty adresy pri každom spustení:
ozvena0 | sudo tee /proc/sys/kernel/randomize_va_space
Ak ho chcete vrátiť do predchádzajúceho stavu, bude stačiť do toho istého súboru napísať 2 namiesto 0.
Druhé systémové volanie: mmap
mmap je druhé systémové volanie používané na prideľovanie pamäte v systéme Linux. Pri volaní mmap sa voľný priestor v akejkoľvek oblasti pamäte mapuje na adresný priestor volajúceho procesu.
Pri prideľovaní pamäte vykonanej týmto spôsobom, keď chcete vrátiť druhý 16KB oddiel s funkciou free() v predchádzajúcom príklade brk, neexistuje žiadny mechanizmus, ktorý by tejto operácii zabránil. Príslušný pamäťový segment sa odstráni z adresného priestoru procesu. Označí sa ako už nepoužívaný a vráti sa do systému.
Pretože alokácia pamäte s mmap je veľmi pomalá v porovnaní s alokáciou s brk, je potrebná alokácia brk.
Pomocou mmap sa každá voľná oblasť pamäte mapuje na adresový priestor procesu, takže obsah prideleného priestoru sa resetuje pred dokončením tohto procesu. Ak reset nebol vykonaný týmto spôsobom, k dátam patriacim procesu, ktorý predtým používal príslušnú pamäťovú oblasť, mohol pristupovať aj nasledujúci nesúvisiaci proces. To by znemožnilo hovoriť o bezpečnosti v systémoch.
Význam prideľovania pamäte v systéme Linux
Alokácia pamäte je veľmi dôležitá najmä v otázkach optimalizácie a bezpečnosti. Ako je vidieť v príkladoch vyššie, úplné pochopenie tohto problému môže znamenať zničenie zabezpečenia vášho systému.
Dokonca aj koncepty podobné push a pop, ktoré existujú v mnohých programovacích jazykoch, sú založené na operáciách prideľovania pamäte. Schopnosť dobre používať a ovládať systémovú pamäť je životne dôležitá ako pri programovaní vstavaného systému, tak aj pri vývoji bezpečnej a optimalizovanej architektúry systému.
Ak sa chcete tiež ponoriť do vývoja jadra Linuxu, zvážte najprv zvládnutie programovacieho jazyka C.
Stručný úvod do programovacieho jazyka C
Prečítajte si ďalej
Súvisiace témy
- Linux
- Pamäť počítača
- Linuxové jadro
O autorovi
Inžinier a vývojár softvéru, ktorý je fanúšikom matematiky a technológií. Vždy mal rád počítače, matematiku a fyziku. Vyvinul projekty herných motorov, ako aj strojové učenie, umelé neurónové siete a knižnice lineárnej algebry. Okrem toho pokračuje v práci na strojovom učení a lineárnych matriciach.
prihlásiť sa ku odberu noviniek
Pripojte sa k nášmu bulletinu a získajte technické tipy, recenzie, bezplatné e-knihy a exkluzívne ponuky!
Kliknutím sem sa prihlásite na odber