V počítačích, aby byl proces spustitelný, musí být umístěn v paměti. K tomu musí být procesu v paměti přiřazeno pole. Alokace paměti je důležitým problémem, který je třeba si uvědomit, zejména v architektuře jádra a systému.

Podívejme se na alokaci paměti Linuxu podrobně a pochopíme, co se děje v zákulisí.

Jak se provádí alokace paměti?

Většina softwarových inženýrů nezná podrobnosti tohoto procesu. Ale pokud jste kandidát na systémové programátory, měli byste o tom vědět více. Když se podíváme na proces alokace, je nutné jít trochu do detailu o Linuxu a glibc knihovna.

Když aplikace potřebují paměť, musí si ji vyžádat od operačního systému. Tento požadavek z jádra bude přirozeně vyžadovat systémové volání. V uživatelském režimu nemůžete alokovat paměť sami.

The malloc() rodina funkcí je zodpovědná za alokaci paměti v jazyce C. Zde je třeba si položit otázku, zda malloc() jako funkce glibc provádí přímé systémové volání.

V jádře Linuxu není žádné systémové volání zvané malloc. Existují však dvě systémová volání pro požadavky na paměť aplikací, které jsou brk a mmap.

instagram viewer

Protože budete ve své aplikaci vyžadovat paměť prostřednictvím funkcí glibc, možná vás zajímá, které z těchto systémových volání glibc v tuto chvíli používá. Odpověď je obojí.

První systémové volání: brk

Každý proces má souvislé datové pole. Systémovým voláním brk se zvýší hodnota přerušení programu, která určuje limit datového pole, a provede se proces alokace.

Přestože je alokace paměti touto metodou velmi rychlá, není vždy možné vrátit nevyužité místo do systému.

Uvažte například, že systémovému volání brk přidělíte pět polí, každé o velikosti 16 kB, pomocí funkce malloc(). Když skončíte s číslem dvě z těchto polí, není možné vrátit příslušný zdroj (dealokaci), aby jej systém mohl použít. Protože pokud snížíte hodnotu adresy tak, aby ukazovala místo, kde začíná vaše pole číslo dvě, s voláním brk, provedete dealokaci pro pole číslo tři, čtyři a pět.

Aby se zabránilo ztrátě paměti v tomto scénáři, implementace malloc v glibc monitoruje místa přidělená v poli procesních dat a poté určí, že se má vrátit do systému pomocí funkce free(), aby systém mohl využít volné místo pro další paměť alokace.

Jinými slovy, po pěti přidělených 16KB oblastech, pokud je druhá oblast vrácena funkcí free() a další 16KB oblast je po chvíli znovu požadováno, namísto zvětšení datové oblasti prostřednictvím systémového volání brk je vrácena předchozí adresa.

Pokud je však nově požadovaná oblast větší než 16 kB, pak se oblast dat zvětší přidělením nové oblasti pomocí systémového volání brk, protože oblast dvě nelze použít. Přestože oblast číslo dvě není používána, aplikace ji nemůže využít kvůli rozdílu velikosti. Kvůli scénářům, jako je tento, nastává situace zvaná vnitřní fragmentace a ve skutečnosti jen zřídka můžete využít všechny části paměti naplno.

Pro lepší pochopení zkuste zkompilovat a spustit následující ukázkovou aplikaci:

#zahrnout <stdio.h>
#zahrnout <stdlib.h>
#zahrnout <unistd.h>
inthlavní(int argc, char*argv[])
{
char *ptr[7];
int n;
printf("Pid %s: %d", argv[0], getpid());
printf("Počáteční přerušení programu: %p", sbrk (0));
pro (n=0; n<5; n++) ptr[n] = malloc (16*1024);
printf("Po 5 x 16 kB malloc: %p", sbrk (0));
volný, uvolnit(ptr[1]);
printf("Po uvolnění druhých 16kB: %p", sbrk (0));
ptr[5] = malloc (16 * 1024);
printf("Po přidělení 6. z 16 kB: %p", sbrk (0));
volný, uvolnit(ptr[5]);
printf("Po uvolnění posledního bloku: %p", sbrk (0));
ptr[6] = malloc (18 * 1024);
printf("Po přidělení nových 18kB: %p", sbrk (0));
getchar();
vrátit se0;
}

Po spuštění aplikace získáte výsledek podobný následujícímu výstupu:

Číslo ./a.out: 31990
Počáteční program přestávka: 0x55ebcadf4000
Po 5 x 16 kB malloc: 0x55ebcadf4000
Po uvolnění druhých 16kB: 0x55ebcadf4000
Po přidělení 6. z 16 kB: 0x55ebcadf4000
Po uvolnění posledního bloku: 0x55ebcadf4000
Po přidělení a Nový18kB: 0x55ebcadf4000

Výstup pro brk se strace bude následující:

brk(NULA) = 0x5608595b6000
brk (0x5608595d7000) = 0x5608595d7000

Jak můžete vidět, 0x21000 byl přidán do koncové adresy datového pole. Můžete to pochopit z hodnoty 0x5608595d7000. Tedy přibližně 0x21000nebo bylo přiděleno 132 kB paměti.

Zde je třeba zvážit dva důležité body. První je přidělení větší částky, než je částka uvedená v ukázkovém kódu. Dalším je, který řádek kódu způsobil volání brk, které poskytlo alokaci.

Randomizace rozložení adresního prostoru: ASLR

Když spustíte výše uvedenou ukázkovou aplikaci jednu po druhé, pokaždé uvidíte jiné hodnoty adresy. Náhodná změna adresního prostoru tímto způsobem výrazně komplikuje práci bezpečnostní útoky a zvyšuje zabezpečení softwaru.

V 32bitových architekturách se však k randomizaci adresového prostoru obecně používá osm bitů. Zvýšení počtu bitů nebude vhodné, protože adresovatelná oblast nad zbývajícími bity bude velmi nízká. Také použití pouze 8bitových kombinací útočníkovi neztěžuje věci dostatečně.

Na druhé straně v 64bitových architekturách, protože existuje příliš mnoho bitů, které lze alokovat pro provoz ASLR, je poskytována mnohem větší náhodnost a zvyšuje se stupeň zabezpečení.

Linuxové jádro také pohání Zařízení se systémem Android a funkce ASLR je plně aktivována v systému Android 4.0.3 a novějším. Už jen z tohoto důvodu by nebylo špatné tvrdit, že 64bitový smartphone poskytuje oproti 32bitovým verzím významnou bezpečnostní výhodu.

Dočasným vypnutím funkce ASLR pomocí následujícího příkazu se zdá, že předchozí testovací aplikace vrací stejné hodnoty adresy při každém spuštění:

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

Chcete-li jej obnovit do předchozího stavu, bude stačit zapsat 2 místo 0 do stejného souboru.

Druhé systémové volání: mmap

mmap je druhé systémové volání používané pro alokaci paměti v Linuxu. Při volání mmap se volné místo v libovolné oblasti paměti mapuje na adresový prostor volajícího procesu.

V alokaci paměti provedené tímto způsobem, když chcete vrátit druhý 16KB oddíl s funkcí free() v předchozím příkladu brk, neexistuje žádný mechanismus, který by této operaci zabránil. Příslušný paměťový segment je odstraněn z adresního prostoru procesu. Je označen jako již nepoužívaný a vrácen do systému.

Protože alokace paměti s mmap je velmi pomalá ve srovnání s těmi s brk, je potřeba alokace brk.

Pomocí mmap je jakákoli volná oblast paměti mapována na adresový prostor procesu, takže obsah přiděleného prostoru je resetován před dokončením tohoto procesu. Pokud by reset nebyl proveden tímto způsobem, mohl by k datům patřícím procesu, který dříve používal příslušnou oblast paměti, přistupovat také další nesouvisející proces. To by znemožnilo hovořit o bezpečnosti v systémech.

Význam alokace paměti v Linuxu

Alokace paměti je velmi důležitá, zejména v otázkách optimalizace a zabezpečení. Jak je vidět na příkladech výše, ne zcela pochopení tohoto problému může znamenat zničení zabezpečení vašeho systému.

Dokonce i koncepty podobné push a pop, které existují v mnoha programovacích jazycích, jsou založeny na operacích alokace paměti. Umět dobře používat a ovládat systémovou paměť je zásadní jak při programování vestavěných systémů, tak při vývoji zabezpečené a optimalizované systémové architektury.

Pokud se chcete také ponořit do vývoje linuxového jádra, zvažte nejprve zvládnutí programovacího jazyka C.

Stručný úvod do programovacího jazyka C

Přečtěte si další

PodíltweetPodílE-mailem

Související témata

  • Linux
  • Paměť počítače
  • Linuxové jádro

O autorovi

Fatih Küçükkarakurt (Zveřejněno 7 článků)

Inženýr a vývojář softwaru, který je fanouškem matematiky a technologií. Vždy měl rád počítače, matematiku a fyziku. Vyvinul projekty herních enginů a také strojové učení, umělé neuronové sítě a knihovny lineární algebry. Navíc pokračuje v práci na strojovém učení a lineárních maticích.

Více od Fatiha Küçükkarakurta

Přihlaste se k odběru našeho newsletteru

Připojte se k našemu zpravodaji a získejte technické tipy, recenze, bezplatné e-knihy a exkluzivní nabídky!

Chcete-li se přihlásit k odběru, klikněte sem