Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Delphi
Sdílení paměti pomocí mapování souborů (3. díl)
sdileni pameti
23. srpna 2002, 00.00 | V tomto dílu seriálu dokončíme serverovou část ukázkové aplikace a trochu při tom zpřesníme naše znalosti o implementaci mapování souborů ve Windows.
V tomto dílu dokončíme serverovou část naší ukázkové aplikace. Minule jsme "vyrobili" procedury reagující na události OnCreate a OnDestroy hlavního formuláře. Dnes se podíváme na samotné sdílení dat s klienty. To nastane při změně textu v komponentě Memo1 (typu TMemo). Budeme tedy obsluhovat její událost OnChange.
Pokud si dobře vzpomínáte na první díl, psal jsem o tom, že výsledkem namapování souboru je ukazatel na začátek jeho dat v paměti. Přiznám se, že jsem malinko lhal. Představte si třeba, že namapujete do paměti gigabajtový soubor. Pak byste mohli zapisovat a psát na libovolná místa celé gigabajtové oblasti paměti. V tu chvíli vyvstane několik problémů:
- Co se soubory většími než 2GB? Dva gigabajty jsou maximální velikost alokovatelné paměti ve Windows, když se tam soubor nevejde, co pak s tím?
- Jak efektivně cacheovat takový soubor? Pokud budete moct náhodně zapisovat kamkoliv do souboru, jakýkoliv obvyklý mechanismus selže a swapování se po dobu operací se souborem nezastaví...
Aby se systém Windows zbavil těchto problémů (hlavně prvního), byly zavedeny tzv. pohledy (views) do namapovaného souboru. Můžete si to představit jako "okénko" do dané paměti - viz obrázek:
Ve skutečnosti příslušná funkce file mappingu vrací ukazatel na začátek takového okénka a manipulovat můžete jen s jeho obsahem - nikoliv tedy s celým namapovaným souborem najednou. Podotýkám, že druhý problém z mého seznamu je tím řešen jen částečně, protože velikost okénka je možno nastavit až na 2GB.
Teď už se raději podívejme na kód procedury TMainForm.Memo1Change:
|
Celá procedura se provádí, jen pokud máme v pořádku přidělený handle file mappingu (viz minulý díl). Funkce MapViewOfFile nám poskytne výše zmiňovaný ukazatel na začátek "okénka". Parametry této funkce jsou celkem přirozené - handle mapování, způsob přístupu k datům (tentokrát chceme psát, v případě čtení bychom použili konstantu FILE_MAP_READ), vyšší a nižší část pozice v souboru, kam ukazatel směřuje (dohromady dávají 64bitové číslo) a nakonec délka okénka. Tu, jak je vidět, volíme rovnou délce textu v editoru plus jedna.
Standardní funkcí StrCopy překopírujeme data za řetězce Memo1.Text do oblasti, kam ukazuje ukazatel P. Tato funkce také za celý řetězec umístí znak #0, což je jednoduchý (navíc ve Windows a v C/C++ standardní) způsob, jak říct "tady je konec řetězce" - kvůli tomu jsme volili délku "okénka" o 1 větší než délka textu. Tohoto způsobu uložení textu výhodně využijeme při tvorbě klientské části aplikace.
Nakonec funkcí UnmapViewOfFile zavřeme "okénko" do namapovaného souboru a pošleme všem oknům (pomocí speciálního handle HWND_BRODCAST) zprávu o změně textu. Na možnou otázku, proč nepoužijeme funkce PostMessage odpovím jednoduše - synchronizace. Tato funkce totiž na rozdíl od SendMessage nečeká, až budou všechny zprávy doručeny, a vrátí ihned po odeslání zpráv řízení volajícímu. Pak by se mohlo snadno stát, že by proběhly třeba další změny textu a přitom by klienti ještě nezpracovali změny předchozí - a vzhledem k tomu, že všichni spolu se serverem přistupují do stejné paměti najednou, mohlo by dojít k problémům. Je to sice okrajový případ (mohl by nastat například při velkém vytížení procesoru), ale když existuje jednoduchý způsob, jak se mu vyhnout, není důvod ho nepoužít.
PříštěPro dnešek je to vše, serverovou část máme tímto dílem dokončenou. To znamená, že příště se můžete podívat na část klientskou.
Celou ukázkovou aplikaci si můžete stáhnout i se zdrojovým kódem (Delphi 3 a vyšší).
Obsah seriálu (více o seriálu):
- Sdílení paměti pomocí mapování souborů (1. díl)
- Sdílení paměti pomocí mapování souborů (2. díl)
- Sdílení paměti pomocí mapování souborů (3. díl)
- Sdílení paměti pomocí mapování souborů (4. díl)
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007