3. feladat
Feladva okt. 12-18, 2009
Határidő nov. 7, 2009
Osztott memória - szinkronizálás nélkül
Feltöltendő állomány(ok)
neve: S03_nn_xxxxxxxxx(_aa).c ahol nn - feladat száma; xxxxxxxxx -
felhasználó azonosítója a linux szerveren; (aa - az illető állomány
funkcionalitásának valamilyen ismertető jegye több modul használata esetén).
- Hozzunk létre két folyamatot: az egyik ismételten ír (véletlenszerűen
generált időközönként) egy osztott memória részben tárolt körkörös pufferbe, a másik pedig ismételten olvas (szintén véletlenszerűen generált
időközönként). Futtassuk a két folyamatot úgy, hogy világossá váljon a két
folyamat szinkronizálásának szükségessége ahhoz, hogy biztosítva legyen
az, hogy az olvasó folyamat helyes adatokat olvasson. Helytelen adatoknak
nevezzük az olyan kiolvasott adatok sorozatát, amely különbözik az
előzőleg beírt adatsorozattól. Ennek érdekébe az író és az olvasó folyamat
is írja ki az éppen beírt/kiolvasott adatot.
- Írjunk egy C programot, mely X-0 játékot játszik egy másikkal. A két
folyamat közötti információcsere egy osztott memória területen keresztül
történik. A programnak
ellenőriznie kell, hogy csak két példányban fut-e.
- Létrehozunk
egy osztott memória területet, melyet két "torpedózó" játékos használ. Az
osztott-memória terület
tartalmaz egy játékos-azonosítót, a célpont
sor- és oszlopszámát, és egy 0 (ha az előző lövés talált) vagy 1 (ha az előző lövés
nem talált) vagy -1 (ha az előző lövés teli találat volt) értéket.
Egy játékos csak akkor lép be a játékba, ha nincs még két játékos, aki már
játszik. A játékosnak megfelelő programban egy 12x12-es mátrixot
generálunk, melyen 7 egymás utáni (vízszintes vagy függőleges)
pozíciót megjelölünk.
A következő célpont kijelölése vagy a billentyűzetről történik vagy egy intelligens
algoritmus segítségével.
- Írjunk
programot, mely létrehoz egy osztott-memória területet, egy 0 és 1 értékeket tartalmazó mátrixszal. Egy másik program n másodpercenként
soronként végigjárja a
mátrixot, és amennyiben valamelyik mátrixelem szomszédságában több, mint 5 b. 1-es érték
van, akkor ez az elem értéke
is 1 lesz, ha pedig több, mint 5 0-s szomszédja
van, 0-vá válik ő is. Az a folyamat, amelyik létrehozta az osztott-memória területet, kiírja a mátrixot mindaddig, ameddig az már nem változik
többé. (vigyázat!
A mátrixot módosító folyamat külön tartsa nyilván a mátrix korábbi értékét, és annak alapján módosítsa az
osztott memóriába írt mátrixelemeket.)
- Egy
program létrehoz egy osztott-memória területet, egy 0 és 1 értékeket tartalmazó mátrixszal. Egy másik program n másodpercenként
oszloponként végigjárja
a mátrixot, és amennyiben valamelyik mátrixelem szomszédságában 5
db. 1-es érték van, akkor
ez az
elem értéke is 1 lesz, ha pedig 5db. 0-s szomszédja van, 0-vá válik ő
is. Az a folyamat, amelyik létrehozta az osztott-memória területet, kiírja a mátrixot mindaddig, ameddig már nem változik
többé. (vigyázat!
A mátrixot módosító folyamat külön tartsa nyilván a mátrix korábbi értékét, és annak alapján módosítsa az
osztott memóriába írt mátrixelemeket.)
- Írjunk
C programot, mely (azonosító, jelzés) adatpárok sorozatát írja ismételten egy osztott-memória területre. Amint befejezte az
írást, egy jelzést küld egy másik folyamatnak, mely olvashatja a sorozatot. A második folyamat minden egyes adatpár esetén elküldi a megadott jelzést az adott azonosítóval
rendelkező folyamatnak.
- Írjunk
folyamatot, mely létrehoz egy osztott-memória területet. Egy másik folyamat, valahányszor indul vagy befejeződik, mindig ír az
osztott-memória területre;
az indításkor egy sajátos adatot, befejezéskor pedig egy másik, a befejezésre jellemző adatot. Az első folyamat
időnként végigjárja az osztott-memória területet és információt ír ki azokról a folyamatokról, amelyek kényszerű módon fejeződtek be (azok, amelyeknek nem sikerült a befejezésre jellemző információt írniuk, ugyanakkor már nem futnak.
Ez utóbbi ellenőrzésére használhatunk shell scriptet).
Tippek / gyakori hibák
- Egyes feladatoknál (pl. 2, 3)
fontos, hogy a két folyamat felváltva írjon az osztott memória területre. Más
lehetőség híján ezt egyelőre a felhasználó oldhatja meg úgy, hogy
futtatáskor előbb az egyik, majd a másik játékos ír be adatot.
- Más esetben, ha növelni
szeretnénk annak a valószínűségét, hogy egyik folyamat már elvégezte
feladatát, mire egy másik lefut, (jobb híján) kísérletezhetünk késleltetés
(sleep) bevezetésével vagy figyelhetjük egy osztott memória változó
értékét (egyik sem ideális megoldás, még akkor sem, ha úgy tűniuk, hogy
"működik").
- ha szükséges, mégis végezhetünk
szinkronizálást jelzések segítségével
- az osztott memória területek
(az üzenetsorokhoz, illetve szemaforokhoz hasonlóan) rendszer szintű
erőforrások, és a számukra fenntartott hely korlátozott, ezért
rendszeresen töröljük az általunk
létrehozottakat.
Ha a C programból nem sikerült törölni (shmctl) egy osztott memória részt,
az alábbi shell parancsokat használhatjuk erre:
> ipcs - információ a létező osztott memória részekről/
szemaforokról / üzenetsorokról
> ipcrm - erőforrás törlése (lásd man)
- Az osztott memóriát használó
folyamatok külön indítható programok legyenek. A feladat jellegétől függően lehet, hogy elég egyetlen programot írnunk, amiből pl. kettőt indítunk, különböző paraméterekkel, viszont semmiképp ne szülő-gyerek folyamatot írjunk.