Na 32bitové architektuře je rozsah adresního prostoru pro adresování RAM:
0x00000000 - 0xffffffff
nebo 4'294'967'295
(4 GB).
Linuxové jádro to rozděluje 3/1 (může být také 2/2 nebo 1/3) na uživatelský prostor (vysoká paměť) a prostor jádra (nízká paměť).
Rozsah uživatelského prostoru:
0x00000000 - 0xbfffffff
Každý nově vytvořený uživatelský proces dostane v této oblasti adresu (rozsah). Uživatelské procesy jsou obecně nedůvěryhodné, a proto je jim zakázán přístup do prostoru jádra. Dále jsou považovány za neurgentní, jako obecné pravidlo se jádro snaží odložit přidělení paměti těmto procesům.
Rozsah prostoru jádra:
0xc0000000 - 0xffffffff
Proces jádra získá svou adresu (rozsah) zde. Jádro má přímý přístup k těmto 1 GB adres (no, ne celý 1 GB, je zde 128 MB vyhrazených pro přístup k velké paměti).
Procesy vytvořené v prostoru jádra jsou důvěryhodné, naléhavé a předpokládá se, že jsou bezchybné, požadavek na paměť je zpracován okamžitě.
Každý proces jádra může také přistupovat k rozsahu uživatelského prostoru, pokud si to přeje. A aby toho bylo dosaženo, jádro mapuje adresu z uživatelského prostoru (vysoká paměť) do svého jaderného prostoru (nízká paměť), pro to je speciálně vyhrazeno výše zmíněných 128 MB.
Zda je rozdělení 3/1, 2/2 nebo 1/3, se řídí pomocí CONFIG_VMSPLIT_...
volba; pravděpodobně můžete zkontrolovat pod /boot/config*
abyste viděli, která možnost byla vybrána pro vaše jádro.
Prvním odkazem, na který je třeba se obrátit, jsou ovladače zařízení Linux (dostupné online i v knižní podobě), zejména kapitola 15, která obsahuje sekci na toto téma.
V ideálním světě by každá součást systému byla schopna zmapovat veškerou paměť, ke které kdy potřebuje přístup. A to je případ procesů na Linuxu a většině operačních systémů:32bitový proces může přistupovat pouze k méně než 2^32 bajtů virtuální paměti (ve skutečnosti asi 3 GB na typické 32bitové architektuře Linuxu). Je to obtížné pro jádro, které musí být schopno zmapovat celou paměť procesu, jehož systémové volání to provádí, plus celou fyzickou paměť plus jakékoli další hardwarové zařízení s mapováním paměti.
Když tedy 32bitové jádro potřebuje namapovat více než 4 GB paměti, musí být zkompilováno s podporou vysoké paměti. Vysoká paměť je paměť, která není trvale mapována v adresovém prostoru jádra. (Nízká paměť je opakem:je vždy mapována, takže k ní můžete přistupovat v jádře jednoduše pomocí dereferencování ukazatele.)
Když z kódu jádra přistupujete k velké paměti, musíte zavolat kmap
nejprve k získání ukazatele z datové struktury stránky (struct page
). Volání kmap
funguje bez ohledu na to, zda je stránka ve velké nebo nízké paměti. Existuje také kmap_atomic
který má přidaná omezení, ale je efektivnější na víceprocesorových strojích, protože používá jemnější zamykání. Ukazatel získaný pomocí kmap
je zdroj:zabírá adresní prostor. Jakmile s tím skončíte, musíte zavolat kunmap
(nebo kunmap_atomic
) uvolnit tento zdroj; pak ukazatel již není platný a obsah stránky nebude přístupný, dokud nezavoláte kmap
znovu.
To je relevantní pro linuxové jádro; Nejsem si jistý, jak to řeší jakékoli unixové jádro.
Velká paměť je segment paměti, který mohou programy v uživatelském prostoru adresovat. Nemůže se dotknout Nedostatek paměti.
Low Memory je segment paměti, který může linuxové jádro adresovat přímo. Pokud jádro musí přistupovat k High Memory, musí ji nejprve namapovat do svého vlastního adresního prostoru.
Nedávno byla představena oprava, která vám umožňuje ovládat, kde se segment nachází. Kompromis je v tom, že můžete odebrat adresovatelnou paměť z uživatelského prostoru, takže jádro může mít více paměti, kterou nemusí před použitím mapovat.
Další zdroje:
- http://tldp.org/HOWTO/KernelAnalysis-HOWTO-7.html
- http://linux-mm.org/HighMemory