Hlavní navigace

Programování pod Linuxem pro všechny (23)

Jakub Matys

Dnes se podíváme na další metodu komunikace mezi procesy. Jedná se o mapování souboru do paměti, které je realizováno funkcí mmap().

Mapovaná paměť umožňuje různým procesům komunikovat prostřednictvím sdíleného souboru. Mapovaná paměť může být použita ke komunikaci mezi procesy nebo k jednoduchému přístupu obsahu souboru. Systém rozdělí obsah souboru na části, které odpovídají velikosti paměťových stránek, a pak je zkopíruje do stránek virtuální paměti. Změna souboru je poté možná pouhým zápisem do paměti. Mapovanou paměť si můžete představit jako vyrovnávací paměť pro celý obsah souboru, čtení celého souboru do této vyrovnávací paměti a nakonec zápis vyrovnávací paměti na disk.

Mapování obyčejného souboru

K mapování obyčejného souboru se používá funkce mmap(). Prvním argumentem je adresa, na kterou se má mapovat soubor. Zadáte-li hodnotu NULL, systém vybere vhodnou adresu za vás. Druhým argumentem je velikost mapy (velikost vyrovnávací paměti) v bytech. Třetím argumentem specifikujete typ ochrany mapovaného prostoru. Typ tvoří trojice kombinací hodnot PROT_READ, PROT_WRITE a PROT_EXEC – hodnoty se kombinují pomocí logcké operace or a odpovídají přístupovým právům pro čtení, zápis a spouštění. Čtvrtým argumentem je příznak specifikující další volby. Pátý argument – deskriptor souboru, jenž má být mapován. Posledním argumentem je posunutí (offset) začátku souboru od začátku mapovaného prostoru.

Příznak je kombinací (pomocí logické operace or) jistých hodnot, jejichž význam je tento:

  • MAP_FIXED – systém bezpodmínečně použije požadovanou adresu (nebo skončí s chybou). Tato adresa musí být násobkem stránky paměti.
  • MAP_PRIVATE – data zapsaná do paměti se neuloží do připojeného souboru, ale do jeho privátní kopie. Žádný jiný proces nemůže „vidět“ tyto zápisy. Uvedenou hodnotu nelze použít s hodnotou MAP_SHARED.
  • MAP_SHARED – zápisy se okamžitě odrážejí v připojeném souboru. Tento mód používejte, pokud chcete použít mapovanou paměť ke komunikace mezi procesy. Mód nelze kombinovat s módem MAP_PRIVATE.

Pokud skončí volání funkce mmap() úspěšně, vrátí ukazatel na začátek mapované paměti. Jinak vrátí hodnotu MAP_FAILED.

Po skončení práce s mapovanou pamětí ji uvolněte pomocí funkce mumap(). Jejími argumenty jsou adresa a délka mapované paměti.

Sdílený prístup k souboru

Prostřednictvím souboru mapovaného do paměti mohou mezi sebou komunikovat procesy, které jsou spojeny týmž souborem. V takovém případě používejte příznak MAP_SHARED, aby se změny v paměti hned promítaly v souboru a aby je viděly i ostatní procesy. Když příznak neuvedete, systém by mohl zápis realizovat prostřednictvím vyrovnávací paměti.

Můžete také systém „donutit“ k zápisu vyrovnávací paměti na disk pomocí funkce msync(). Její první dva parametry specifikují oblast mapované paměti, stejně jako v případě funkce munmap(). Třetím parametrem je příznak s těmito možnými hodnotami:

  • MS_ASYNC – aktualizace souboru se naplánuje, ale nemusí se realizovat před návratem funkce.
  • MS_SYNC – aktualizace souboru proběhne okamžitě. Volání funkce se zablokuje, dokud se zápis do souboru neukončí. Příznaky MS_SYNC a MS_ASYNC nelze použít současně.
  • MS_INVALIDATE – všechna ostatní mapování souboru se stanou neplatnými tak, aby mohly „vidět“ aktualizované hodnoty.
msync(adresa, delka, MS_SYNC | MS_INVALIDATE);

Tento řádek provede aktualizaci souboru na adrese adresa o velikosti delka.

Pokud chcete používat mapovanou paměť ke komunikaci mezi více procesy, musíte přistupovat k soboru pomocí určitého protokolu, aby nedocházelo k souběhu. K ochraně před současným vícenásobným přístupem do mapované paměti lze použít semafory. Alternativně lze použít systémové volání fnctl k definici zámku na čtení a zápis do souboru.

Privátní mapování

Pokud použijete ve funkci mmap() příznak MAP_PRIVATE, budou všechny zápisy do mapované paměti viditelné jen tím procesem, který funkci volal. Místo přímého zápisu do stránky sdílené všemi procesy zapisuje aktuální proces do privátní kopie této stránky. Všechna následující čtení a všechny následující zápisy používají tuto stránku.

To by bylo pro dnešek vše. Příště se podíváme na datové kolony neboli roury.

Našli jste v článku chybu?
13. 7. 2004 20:57
hkmaly (neregistrovaný)

Sdilena pamet sama o sobe je synchronizacnim primitivem. Semafor, kterym synchronizujeme pristup k ni, muzeme realizovat primo v ni synchronizacnimi instrukcemi (xchg, cmpxchg8b, ...) nebo na uniprocesoru libovolnymi instrukcemi.

12. 7. 2004 9:38
Yenya (neregistrovaný)

V textu pisete: -- MAP_SHARED - zápisy se okamžitě odrážejí v připojeném souboru. Tento mód používejte, pokud chcete použít mapovanou paměť ke komunikace mezi procesy. Mód nelze kombinovat s módem MAP_PRIVATE. -- Zajimave je to slovo "okamzite", zejmena kdyz dale popisujete msync(2). Pokud by to bylo "okamzite", neni msync(2) potreba. Ve skutecnosti je to tak, ze rozumne implementace VM se chovaji tak, ze zapisy do mmap(2)ovane oblasti s MAP_SHARED se projevuji naraz vsude vcetne cteni t…