PVM ismertetô

(C) 1995 Csizmazia Balázs
(C) Lásd alább az eredeti PVM-copyrightet

Az anyag egy PVM elôadásom rövid kivonata - szabadon terjeszthetô. A leírás helyességéért, a használatából eredô esetleges károkért sem Csizmazia Balázs sem pedig a dokumentum más módosítója nem vállal felelôsséget.

Az anyag "unsupported", nekem a továbbiakban semmi érdekem/célom nem fűzôdik hozzá, nem fogom módosítani, stb ...

A Csizmazia Balázs által rögzített copyright feltételeken bárki tetszése szerinti módosításokat végezhet azzal a feltétellel, hogy az esetlegesen (akár anyagi ellenszolgáltatásért) vállalt kötelezettségei az eredeti szerzôre (Csizmazia Balázsra) nem vonatkoznak semmilyen körülmények között, és összhangban marad az eredeti PVM-copyrighttal.

Az anyag a PVM User's Guide egy részleges "kijegyzetelésének" tekinthetô; kisebb módosításokat ugyan végeztem rajta, de nem tartalmaz PVM programozási technikákat, példaprogramokat, nem tartalmazza a PVM függvényeinek referencia-kézikönyv szerű leírását.

AMENNYIBEN valaki ezeket a feltételeket nem tartja elfogadhatónak, akkor e dokumentumot nem használhatja, nem terjesztheti.

A PVM copyright-je (ami mind a szoftverre, mind pedig a vele szállított dokumentációra is vontakozik) angolul így hangzik [ide szebb lenne egy magyarra fordítás, de nincs jogi szakfordítói végzésem, így inkább ettôl eltekintek ...] :


PVM 3.2: Parallel Virtual Machine System 3.2

University of Tennessee, Knoxville TN.
Oak Ridge National Laboratory, Oak Ridge TN.
Emory University, Atlanta GA.
Authors: A. L. Beguelin, J. J. Dongarra, G. A. Geist,
W. C. Jiang, R. J. Manchek, B. K. Moore, and V. S. Sunderam
(C) 1992 All Rights Reserved

NOTICE

Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted provided that the above copyright notice appear in all copies and that both the copyright notice and this permission notice appear in supporting documentation.

Neither the Institutions (Emory University, Oak Ridge National Laboratory, and University of Tennessee) nor the Authors make any representations about the suitability of this software for any purpose. This software is provided ``as is'' without express or implied warranty.

PVM 3.2 was funded in part by the U.S. Department of Energy, the National Science Foundation and the State of Tennessee.

TARTALOM:


0. Elosztott rendszerek - címszavakban

Definició:
Elosztott rendszernek tekinthetjük a több (nem osztott memóriával ellátott) számítógépen futó olyan alkalmazásokat, ahol az alkalmazás felhasználójának nem kell tudnia az alkalmazás kezeléséhez arról, hogy az alkalmazás több számítógépen fut.
Elônyeik:
  • Gazdaságos (több kisebb teljesítményű, olcsó komponensbôl állítható össze)
  • Megbízható (egy gép kiesésekor még nem dôl össze a világ)
  • Erôforrásmegosztást támogatja (valamilyen hálózat segítségével)
  • Hátrány:
  • Kevés a kiforrt szoftver-technológia (illetve a meglevô technológiák nagy része nem elosztott (azaz centralizált) jegyeket visel magán -- pl. a központi nyilvántartások ...)
  • Gyenge a tömegesen rendelkezésre álló hardware minôsége

  • 1. Bevezetés

    A PVM (Parallel Virtual Machine) rendszert az Oak Ridge National Laboratories több más résztvevôvel együtt fejlesztette ki. Céljuk egy olyan szoftver-rendszer kifejlesztése volt, mely támogatja elosztott alkalmazások készítését - leginkább UNIX környezetben (vagyis maga a PVM csak kevés hagyományos értelemben vett operációs rendszer szolgáltatást biztosít, legfôbb profiljának az elosztott alkalmazás-komponensek kommunikációjának megszervezése tekinthetô). A PVM lehetôséget ad több - például TCP/IP protokollal hálózatba kapcsolt - számítógép erôforrásainak összevonására, ezzel egy "virtuális számítógép" létrehozására, amelyben a futó programok egységes interfésszel kapcsolódhatnak egymáshoz.

    A PVM-rôl számos jó minôségű (ingyenes) dokumentáció elérhetô - többek közt a "PVM 3 USER'S GUIDE AND REFERENCE MANUAL", ami tartalmazza a PVM installálásához/alkalmazásához szükséges (talán) összes információt.

    Ez az ismertetô egy áttekintést nyújt a PVM lehetôségeirôl - lényegében néhány elem bemutatásával. A rendszerrel végzett érdemi munkához valószínűleg szükség lesz az eredeti PVM leírásra valamint a PVM könyvtár függvényeirôl készült online leírásokra.

    2. A PVM rendszer szerkezete

    A rendszer két fôbb komponensbôl áll: egyrészt egy eljáráskönyvtárból, amit a PVM-et használó alkalmazásokhoz hozzá kell linkelni (az ezekben levô eljárásokkal érhetjük el a PVM szolgáltatásait programjainkból), másrészt pedig van egy önállóan futtatható PVM-démon része, amely gépenként és felhasználónként egy-egy példányban fut, és ez az, ami a PVM szolgáltatások tényleges implementációját tartalmazza. A PVM elterjedtségének egyik oka a szabad elérhetôsége, valamint az, hogy számos hardvergyártó a többprocesszoros/elosztott számítógépeihez ilyen interfészt (is) biztosít. Továbbá meg kell említeni vele kapcsolatban azt is, hogy hordozható program; valamint a UNIX operációs rendszert bôvíti ki -- ezzel nyilvánvalóan lehetôvé válik párhuzamos programok szabványos UNIX környezetbe történô beágyazására.

    Ha például van két számítógépünk, amelyekbôl a PVM segítségével egyetlen virtuális gépet akarunk csinálni, azt megtehetjük úgy, hogy mindkét gépen elindítjuk a (megfelelôen felkonfigurált) PVM-démont, majd el kell indítani a PVM-et használó alkalmazásokat. Ha egy gépet több különbözô felhasználó akar egy virtuális géppé összekapcsolni, akkor mindegyik felhasználónak saját PVM-démont kell indítania, viszont egy felhasználónak elég csak egy PVM-démont futtatnia, ez megszervezi a felhasználó összes (akár több is!) elosztott alkalmazásának futtatását.

    Elosztott alkalmazások készítésekor az egyes alkalmazás-komponenseket különálló programokként (mondjuk UNIX processzként ...) kell megírni, azok szinkronizációjára/adatcseréjére kell a PVM-et használnunk; vagyis a PVM nem biztosít eszközöket összetett alkalmazások komponenseinek automatikus párhuzamosításához. A PVM lehetôséget nyújt arra, hogy egy "mezei" UNIX processz bekapcsolódjon a virtuális gépbe, valamint arra is, hogy egy PVM-be kapcsolódott UNIX processz (a továbbiakban PVM-processz) kilépjen a PVM által biztosított virtuális gépbôl, valamint lehetôség van PVM-processzek egymás közti kommunikációjára, PVM-processzek úgynevezett PVM-processzcsoportokba kapcsolására, és biztosított egy-egy ilyen csoport összes tagja részére az üzenetküldés is, valamint egy-egy csoportba új tag felvétele és tagok törlése a csoportból.

    3. A PVM konfigurációja

    A PVM telepítése nem okozhat különösebb gondot, s részletes leírása megtalálható az installációs csomagban. Felerülô kérdések, problémák esetén segítségre lehet a PVM FAQ (tömörített Postscript állomány, 51KB).

    4. A PVM elindítása

    A PVM virtuális gép felélesztéséhez el kell indítanunk az ehhez szükséges programot: vagy a PVM-démont (neve pvmd3) vagy pedig a PVM konzolt (neve pvm). Az utóbbi a virtuális gép felélesztése mellett elindít egy PVM-konzolt, amivel interaktivan kapcsolhatunk és törölhetünk gépeket a virtuális gépbôl, interaktivan indíthatunk (és lôhetünk le ...) PVM-processzeket, és talán legfontosabb parancsa a help (amivel a további parancsok használatához kérhetünk segítséges a rendszertôl). Például fontos parancsok a következôk:
    halt: lelövi az összes futó PVM-processzünket, és kilép a PVM-bôl, leállítja a PVM-démont
    spawn: új PVM-processzt indít
    kill: egy futó PVM-processzt lelô
    reset: lelövi az összes futó PVM-processzt a konzol kivételével, a PVM-démonokat pedig nem bántja.

    5. PVM szolgáltatások C nyelvű interfésze

    A PVM szolgáltatások igénybevehetôk mind C mind pedig Fortran programozási nyelven készült programokból - eljáráshívások formájában. Most a C-bôl hívható eljárások rövid ismertetése következik - a teljesség igénye nélkül, az eredeti PVM User's Guide szerkezete alapján (nagyjából ... egyes, pl. a PVM konfigurálását végzô eljárásokat nem mutatom be -- ui. azokat a funkciókat nagyrészt elvégezhetjük a PVM konzolon, és nem kell C-ben kódolni). Nem lesz szó pl. a dinamikus konfigurációt végzô pvm_addhosts, pvm_delhosts, stb. függvényekrôl.

    5.1. PVM-processzek kezelése

    Minden egyes PVM-processz rendelkezik egy egész típusú processz-azonosítóval (a UNIX processzek azonosítójához hasonló a szerepe, és fontos megemlíteni, hogy a PVM-processz azonosítónak semmi köze sincs a UNIX processzeinek a processz-azonosítójához). A PVM-processz azonosítókat a továbbiakban tid-del jelölöm.

  • pvm_spawn

    Egy új PVM-processzt a pvm_spawn eljárással hozhatunk létre. Ennek alakja a következô:

    int pvm_spawn(char *task, char **argv, int flag, char *where, int ntask, int *tids);

    Az elsô argumentum (task) az elindítandó PVM-processzt tartalmazó végrehajtható fájl nevét adja meg; a második (argv) az átadandó program-argumentumokat tartalmazza; a harmadik paraméter kijelöli, hogy hol kell elindítani az új PVM-processzünket (pl. CPU-architektúrára tartalmazhat utalást, de gyakran a processzt indító számítógép CPU-ján kell az új PVM-processzt futtatni, ezért gyakori, hogy az ezt kijelölô PvmTaskDefault (0 értékű) konstans adják itt meg). Amennyiben az alkalmazásnak speciális igényei vannak az új PVM-processz elindításával kapcsolatban, akkor azt a flag argumentumban jelezheti, és ilyenkor kell a where argumentumban megadni azt, hogy (fizikailag) hol is akarjuk a programunkat elindítani. Az ntask paraméterben adhatjuk meg, hogy hány példányban akarjuk a PVM-processzt elindítani, majd a rendszer a tids tömbben adja vissza az elindított PVM-processzek azonosítóit (tid-jeit). A függvény visszatérési értéke a ténylegesen elindított új PVM-processzek száma.

    Használatára példa:

    numt = pvm_spawn( "progi1", NULL, PvmTaskHost, "macska", 1, &tids[0]);

    Ami elindít a macska nevű hoston egy új PVM-processzt a progi1 nevű programból. Megjegyezzük, hogy a PvmTaskHost paraméter arra utal, hogy kijelöljük a negyedik argumentumban, hogymelyik hoston akarjuk elindítani az új PVM-processzt. Ha itt PvmTaskDefault értéket adtunk volna meg, akkor a PVM rendszer maga választhatott volna egy hostot, ahol a programot elindítja. A tids változó egy egészeket tartalmazó vektor.

  • pvm_exit

    Egy PVM-processz a pvm_exit eljárás végrehajtásával léphet ki a PVM felügyelete alól.

  • pvm_mytid

    Egy PVM-processz a saját tid-jét ezzel kérdezheti le. A függvény visszatérési értéke az új PVM-processz tid-je. Nincs paramétere.

  • pvm_parent

    Egy PVM-processz a szülôjének a tud-jét kérdezheti le. Visszatérési értéke a szülôjének a tid-je. Nincs paramétere.

  • pvm_kill

    Lelövi azt a PVM-processzt, amelynek a tid-jét megadtuk az argumentumában.

    5.2. Kommunikáció

    A PVM eszközei közt vannak primitív, UNIX signal-okat (magyarul nevezhetjük ôket SOFTWARE-interruptoknak :-) használó kommunikációs eljárások (amelynek használatát nem javasoljuk egyes UNIX implementációk signal-kezelésének néhány tökéletlen vonása miatt ...), valamint vannak összetettebb adatszerkezetek/adatterületek processzek közötti mozgatására is eszközök. Megjegyezzük, hogy a Linux implementáció signal-kezelése nem minôsül tökéletlennek, így azon megbízható kommunikációt biztosítanak a Linux signalok használata.

  • pvm_sendsig

    A függvény segítségével egy adott signalt (UNIX signalt) küldhetünk valamelyik PVM-processznek. A függvény elsô paramétere a kívánt PVM-processz PVM tid-je (ez nem ugyanaz, mint a kill() UNIX rendszerhívás, ugyanis az nem képes pl. "hálózaton keresztül" más hoston futó processzeknek signal-t küldeni).

  • pvm_notify

    A függvény alakja a következô:

    int pvm_notify(int about, int msgtag, int ntask, int *tids)

    Hatása pedig az, hogy a késôbbiekben az about argumentumban specifikált esemény bekövetkeztekor egy olyan üzenetet küld a tids vektorban megadott tid-del azonosított PVM-processzeknek, amely üzenet msgtag része (ez az üzenetek egy komponensét jelöli) megegyezik a függvény második argumentumában megadott értékkel.

    Az about paraméter lehet PvmTaskExit (ekkor az esemény egy PVM processz bvefejezôdése), PvmHostDelete (ekkor az esemény egy bekapcsolt host kiesése lesz), PvmHostAdd (ekkor az esemény egy új host PVM-be kapcsolása).

    5.3. Hibaüzenetek

    A legutolsó sikertelen (nem elvégezhetô) PVM függvényhívás sikertelenségének az okát a pvm_perror(char *msg) függvénnyel irathatjuk ki -- egy programozó által megadott megjegyzés-üzenet kíséretében.

    5.4. A PVM-processzek egymásközti üzenetátadása

    A PVM processzek egymás közt üzenetekkel kommunikálhatnak. E kommunikáció elsô lépéseként inicializálni kell az üzenetet tartalmazó buffert, majd fel kell tölteni az elküldendô üzenettel, végül el lehet küldeni a címzettnek. Az elküldés után az üzenetet tartalmazó buffer felszabadítható. Még meg kell említeni azt is, hogy az üzenet fogadása kétféleképpen történhet: blokkolva vagy blokkolás nélkül (ez azt jelenti, hogy érkezett üzenet hiányában a üzenetre váró PVM processz továbbfut-e üzenet beolvasása nélkül vagy megáll és vár, amíg egy üzenetet kap).

    Az üzenetátadás során heterogén hálózatban (ahol több, különféle architekturájú host is elôfordulhat) felmerülhetnek adatok reprezentációjának eltérésébôl származó problémák (pl. a 2 vagy 4 byteos egész számoknál a reprezentáció bytesorrendje eltér például az i386 és Motorola 68000 architektúrákon -- ha pl. egy 4 byteos egész számot e két architektúra között kell átvinni, akkor a byteok átvitelén kívül gondoskodni kell a byteok sorrendjének megfelelô cseréjérôl is). A PVM rendszerben ezt a problémát úgy lehet megoldani, hogy az adatokat elküldés elôtt egy hálózati ("külsô", szabványosított) ábrázolási formára kell alakítani, az adat/üzenet fogadáskor pedig a fogadó állomás feladata lesz a hálózati ábrázolási formára történô adatkonverzió. A PVM rendszer hálózati adatábrázolásra a Sun XDR (eXternal Data Representation) ábrázolásmódját alkalmazza.

    5.4.1. Buffer(de)allokálás

  • pvm_mkbuf

    A PVM rendszerben üzenetküldés céljából több üzenet-buffert is allokálhatunk, és ezek közül kijelölhetjük, hogy melyik legyen az aktív küldési illetve aktív fogadási buffer: vagyis melyikbe akarunk adatokat bepakolni a bepakoló-függvényekkel (adatelküldés céljából) illetve melyikbôl akarunk adatokat kiolvasni (egy megkapott üzenetbôl). Megjegyezzük, hogy az adatbeolvasási és az adatküldési buffer megegyezhet.

    Egy új üzenet-buffert a pvm_mkbuf függvénnyel hozhatunk létre. Ennek egyetlen argumentuma van (egy egész szám, amely a buffer tartalmának az összeállítási módját értelmezését/reprezentációját írja le), visszatérési értéke pedig (szintén egy egész szám) a létrehozott buffer egyértelmű azonosítóját tartalmazza.

    A pvm_mkbuf argumentumának értéke a következô (makrókkal definiált konstans) értékek valamelyike lehet:

  • PvmDataDefault: A bufferben levô adatok XDR formában lesznek elküldve.

  • PvmDataRaw: A bufferben levô adatok nem lesznek konvertálva - a bufferben levô byteok a bufferbeli sorrendjükben lesznek elküldve, az üzenet címzettje ugyanabban a sorrendben fogja megkapni.

  • PvmDataInPlace: A buffer csak pointereket tartalmaz az elküldendô adatokra illetve azok hosszát.

  • pvm_initsend

    Ezzel az adatküldési buffert ki lehet üríteni, és ez egyben inicializálni is fogja azt. Ennek egyetlen argumentuma van: ugyanaz, mint az elôzôekben ismertetett pvm_mkbuf függvény argumentuma (ugyanazokat az értékeket veheti fel, és ugyanazt kell vele megadni).

    Visszatérési értéke az egyedi buffer-azonosító.

    Megjegyezzük, hogy ez a függvény meghívja a pvm_mkbuf függvényt egy új buffer létrehozására, és az újonnan létrehozott adatbuffert kijelöli új aktív adatküldési buffernek (annyivel tud többet).

    Továbbá megjegyezzük, hogy ez a függvény felszabadítja az aktív küldési buffert a pvm_freebuf függvénnyel, így ez elôtt azt nem kell végrehajtani -- a pvm_initsend függvények ciklikus végrehajtása nem eredményezi a memória elfogyását.

  • pvm_freebuf

    Egyetlen argumentuma az eldobandó (továbbiakban már nem használt) üzenet-buffer egyedi azonosítója. A függvény eredményeként a paraméterben kijelölt buffer által lefoglalt memóriaterületeket a rendszer felszabadítja, visszarakja a memória szabad-listára.

  • pvm_getsbuf

    Nincs argumentuma. Visszatérési értéke az aktuális (aktív) küldési buffer azonosítója.

  • pvm_getrbuf

    Nincs argumentuma. Visszatérési értéke az aktuális (aktív) fogadási buffer azonosítója (ez az, amelyikbôl adatokat tudunk kiolvasni a késôbb bemutatásra kerülô adatbeviteli függvényekkel).

  • pvm_setsbuf

    Meg lehet változtatni vele az aktív küldési buffert. Egyetlen argumentuma van, amely megadja az új aktív küldési buffer egyedi azonosítóját kell, hogy tartalmazza, és visszaadja a korábban aktív küldési buffer azonosítóját.

  • pvm_setrbuf

    Meg lehet változtatni vele az aktív fogadási buffert. Egyetlen argumentuma van, amely megadja az új aktív fogadási buffer egyedi azonosítóját kell, hogy tartalmazza, és visszaadja a korábban aktív fogadási buffer azonosítóját.

    5.4.2. Adatbepakolás

    Az adatok elküldése elôtt az elküldendô adatokat be kell pakolni a küldési bufferbe. Erre valók az alábbi függvények:

    pvm_pkbyte
    pvm_pkcplx
    pvm_pkdcplx
    pvm_pkdouble
    pvm_pkfloat
    pvm_pkint
    pvm_pklong
    pvm_pkshort
    pvm_pkstr

    Az utolsó kivételével mindegyiket a következô paraméterekkel hívhatjuk:

    int pvm_pkXXX( XXXtype *ptr, int nitems, int stride);

    Ahol XXXtype típus a pvm_pkXXX-ben levô adattípusból származtatható. Az elküldendô adatokra az elsô argumentum mutat. A második argumentum adja meg, hogy az elsô argumentum által mutatott helyrôl hány adatelemet kell az aktuális küldési bufferbe átpakolni (a megfelelô adatábrázolási bufferbe). A stride argumentum értékben az adatpakolási lépéshosszt lehet megadni (ez az érték egyszerűen rendre hozzá lesz adva az elsô argumentumban megadott pointerhez (összesen nitems-szer a szokásos C pointer-aritmetikával!!), és az így érintett memóriacímeken levô adatokat pakolja be a küldési bufferbe).

    A pvm_pkcplx függvény complex típusú adatot kezel, amelyet a PVM rendszerben deklaráltak egy rekord típusként, melynek két komponense van: r a valós, és f az imaginárius rész neve (mindkettô float típusú -- a dcplx esetén pedig double típusú).

    A pvm_pkstr függvény prototípusa a következô:

    int pvm_pkstr( char *str );

    Megjegyezzük, hogy míg a Sun XDR lehetôséget nyújt rekord/unió típusú adat ábráolására, addig itt erre nincs automatikusan megoldás: ehelyett a struktúra elemeit nekünk kell egyenként feldolgoznunk -- a típusuknak megfelelô módon.

    5.4.3. Adatkipakolás

    Ez nagyon hasonlít az adatbepakolásra: ehhez a következô függvényeket használhatjuk:

    pvm_upkbyte
    pvm_upkcplx
    pvm_upkdcplx
    pvm_upkdouble
    pvm_upkfloat
    pvm_upkint
    pvm_upklong
    pvm_upkshort
    pvm_upkstr

    Ezeknek a függvényeknek az argumentumaik ugyanazok, mint az adatbepakoló párjuknál (de itt az elsô argumentum azt adja meg, hogy a kipakolt adatokat hová akarjuk tenni a memóriában). Ezek a függvények az aktív fogadási bufferbôl olvasnak adatokat.

    5.5. Adatátvitel (küldés, fogadás)

    Itt a PVM üzenetküldésérôl ill. üzenetfogadásáról lesz szó. Az üzenetfogadó eljárás alég dinamikus ill. kiterjeszthetô abban az értelemben, hogy definiálhatunk akár saját szűrôfeltételeket is, amelyekkel kiválaszthatjuk a következô "beolvasandó" (fogadandó ...) üzenetet a PVM processzünk címére küldött üzenetek közül (ld. errôl a pvm_recvf függvény online leírását).

    A pvm_advise függvényrôl nem írok itt (ezzel lehet speciális kommunikációs útvonalat kiépíteni két PVM-processz között, mondjuk egy TCP csatornán, a hatékonyság növelése érdekében).

    5.5.1. Adatküldés

    A legegyszerűbb adatküldô eljárás a pvm_send, melynek elsô paramétere a címzett PVM-processz tid-je, a második argumentuma pedig egy egész érték (msgtag), amely az üzenetek osztályozására használható: megadható vele, hogy a küldött üzenet milyen osztályba tartozik. (Késôbb látni fogjuk, hogy az adatfogadási műveleteknek meg kell adni, hogy mely osztálybeli üzenetre várunk, ezért jó ez a mezô.) Megjegyezzük, hogy az msgtag argumentum (az üzenet osztályának az azonosítója) is konvertálva lesz hálózati (külsô) adatábrázolási formára.

    Egy művelettel ugyanazt az üzenetet több PVM processznek is elküldhetjük:

    int pvm_mcast( int *tids, int ntask, int msgtag)

    alakú az erre való művelet: itt az elsô argumentum egy egész (int) tömb azonosítója, amely a címzett PVM processzek azonosítóit tartalmazza; a benne levô taszkok számát pedig a második (ntask) paraméterben kell megadni.

    5.5.2. Adatfogadás

    Az adatfogadó műveletnek két változata van: az egyik blokkol és vár egy adott osztályba tartozó üzenet érkezésére; a másik pedig visszatér adatbeolvasás nélkül akkor, ha nincs a kívánt osztályba tartozó beérkezett üzenet.

    A nem-blokkoló eljárás a következô alakú:

    int pvm_nrecv( int tid, int msgtag)

    Ahol tid arg-ban megadhatjuk, hogy kitôl várunk üzenetet; a msgtag-ban pedig megadhatjuk a várt üzenet osztályát. Bármelyik argumentumban megadhatunk -1 értéket, ami azt jelenti, hogy az argumentum értéke nem érdekel minket.

    A blokkoló eljárás a következô alakú:

    int pvm_nrecv( int tid, int msgtag)

    Az argumentumai ugyanazok mint a nem-blokkoló párjánál.

    Mindkét függvény visszatérési értéke a megkapott üzenet üzenet-bufferének az egyedi azonosítója, ha sikerült üzenetet olvasni. Ha nem volt beolvasandó üzenet, akkor 0-t ad vissza.

    A hasonló paraméterezésű pvm_probe függvénnyel megnézhetjük, hogy érkezett-e adott küldôtôl adott osztálybeli üzenet; és ha igen, akkor visszakapjuk az üzenethez tartozó buffer azonosítóját, ahova a rendszer az üzenetet beolvassa. Az érkezô üzenetet bennmarad a "feldolgozatlan" üzenetek között (egy újabb hívása ugyanazt az üzenetet látja majd).

    Egy üzenetbufferrôl (a benne tárolt üzenetrôl, osztálykódjáról, hosszáról) információkat a pvm_bufinfo függvénnyel nyerhetünk.

    5.6. Processz-csoportok

    A PVM rendszer lehetôséget nyújt processz-csoportok szervezésére. Egy PVM processz bármikor beléphet egy csoportba -- ezzel csoporttaggá válik -- illetve bármikor kiléphet egy csoportból. A csoportoknak nevet adhatunk, a csoportnév ASCII karakterek sorozatából állhat. A csoportokkal kapcsolatban több művelet is van: üzenet küldése az összes csoporttag számára (az üzenet küldôje nem kell, hogy tagja legyen a csoportnak) valamint lehetôség van a csoporttagok állapotának szinkronizálására.

    Egy PVM-processz a pvm_joingroup függvényhívással lehet tagja egy processz-csoportnak. A függvény egyetlen paramétere a csoport neve. A függvény visszatérési értéke egy csoporton belüli azonosító szám (instance id. - példány-azonosító).

    Egy PVM-processz a pvm_lvgroup függvényhívással léphet ki egy csoportból. Egyetlen argumentuma a csoport neve, amibôl a PVM-processz ki akar lépni.

    A fent említett példány-azonosító (instance id.) és a PVM processz-azonosítók (tid-ek) kapcsolatát a pvm_gettid és a pvm_getinst függvény teremti meg.

    Egy csoport résztvevôinek a számát a pvm_gsize függvénnyel kérdezhetjük le: egyetlen argumentuma a csoport neve.

    Egy csoport összes tagjának küldhetünk egy művelettel üzenetet a pvm_bcast függvénnyel. Ennek alakja a következô:

    int pvm_bcast( char *group, int msgtag )

    (itt az elsô argumentum a csoport neve; a második argumentum az üzenet típusának az azonosítója; visszatérési értéke negatív ha valami hiba történt.) Megjegyezzük, hogy a küldô nem kapja meg az így küldött üzenetet, ha tagja a megadott nevű csoportnak.

    Egy csoport szinkronizálására szolgál a pvm_barrier függvény. Ennek az alakja a következô:

    int pvm_barrier(char *group, int count)

    Ahol az elsô a csoportnév; a második argumentum pedig egy szám. A függvény eredményeként a hívó PVM-processz blokkolni fog egészen addig, amíg (count) darab csoporttag meg nem hívja e függvényt. A többi processznek ugyanezekkel az argumentumokkal kell meghívnia e függvényt.

    Ezzel például megoldható az, hogy egyszerre "induljanak el" egy processz-csoport tagjai: például tekintsünk egy olyan szolgáltatást, ahol a szolgáltatást 17 (ez a szám csak példa) darab PVM-processz nyújtja egy processz-csoportba szervezôdve. Azt szeretnénk, hogy a szolgáltatást nyújtó processzek ugyanabban az állapotban legyenek a működésük folyamán. Ehhez az is szükséges, hogy kezdetben már szinkronizálják az állapotukat, a hozzájuk érkezô üzeneteket mind megkapják ...

    Megjegyzés: nem kötelezô, de ajánlott betartani a következôket:

    • csoportok kommunikációját általában csoporton belül használjuk
    • a PVM (ill. más rendszer) segítségével készült termékekben a "felhasználó" felé a szolgáltatásokat ne tisztán PVM eszközökkel nyújtsuk. A "felhasználónak" ne kelljen tudnia az implementáció részleteirôl.


    Csizmazia Balázs, e-mail: csb@ullman.inf.elte.hu