mmap
(při použití s MAP_ANONYMOUS
) alokuje část paměti RAM, kterou lze umístit kamkoli do virtuálního adresového prostoru procesu a kterou lze uvolnit později (pomocí munmap
) nezávisle na všech ostatních přiděleních.
brk
změní koncovou adresu jedné souvislé "arény" virtuálního adresového prostoru:pokud je tato adresa zvýšena, přidělí více paměti aréně, a pokud se sníží, uvolní paměť na konci arény. Paměť je tedy přidělena brk
může být uvolněn zpět do operačního systému pouze tehdy, když je souvislý rozsah adres na konci arény proces již nepotřebuje.
Pomocí brk
pro malé alokace a mmap
pro velké alokace je heuristika založená na předpokladu, že u malých alokací je pravděpodobnější, že všechny budou mít stejnou životnost, zatímco u velkých alokací je pravděpodobnější, že budou mít životnost, která nekoreluje s životností jiných alokací. Velké alokace tedy používají systémové primitiva, které jim umožňuje uvolnit alokace nezávisle na čemkoli jiném, a malé alokace používají primitiva, která tak neučiní.
Tato heuristika není příliš spolehlivá. Aktuální generace malloc
implementace, pokud si dobře pamatuji, se na brk
úplně vzdala a používá mmap
za všechno. malloc
Předpokládám, že implementace, na kterou se díváte (ta v knihovně GNU C, na základě vašich značek), je velmi stará a hlavně se nadále používá, protože nikdo není dost odvážný, aby riskoval její výměnu za něco novějšího, co bude pravděpodobně ale ne určitě být lepší.
tak proč malloc volá mmap, když jde o přidělení velké velikosti paměti?
Krátká odpověď je pro lepší efektivitu na novějších implementacích Linuxu a aktualizované algoritmy alokace paměti, které jsou s nimi dodávány. Ale mějte na paměti, že toto je téma velmi závislé na implementaci a proč a proč by se velmi lišily pro různé ročníky a příchutě konkrétního operačního systému Linux, o kterém se diskutuje.
Zde je poměrně nedávný zápis týkající se nízkoúrovňových částí mmap()
a brk()
hrát v alokaci paměti Linuxu. A ne tak nedávný, ale stále relevantní článek Linux Journal, který obsahuje určitý obsah, který je velmi aktuální pro toto téma, včetně tohoto:
Pro velmi velké požadavky malloc() používá systémové volání mmap() k nalezení adresovatelného paměťového prostoru. Tento proces pomáhá snižovat negativní účinky fragmentace paměti když jsou velké bloky paměti uvolněny, ale uzamčeny menšími, nověji přidělenými bloky ležícími mezi nimi a koncem přiděleného prostoru. V tomto případě, kdyby byl blok alokován pomocí brk(), zůstal by systémem nepoužitelný, i kdyby jej proces uvolnil.
(důraz můj)
Ohledně brk()
:
mimochodem "...mmap() v raných verzích Unixu neexistovala. brk()
byl v té době jediný způsob, jak zvětšit velikost datového segmentu procesu. První verzí Unixu s mmap() byl SunOS v polovině 80. let, první open-source verze byla BSD-Reno v roce 1990. ". Od té doby byly moderní implementace algoritmů pro alokaci paměti přepracovány s mnoha vylepšeními, což výrazně snížilo potřebu zahrnout použití brk()
.