next up previous contents
Next: Kritikus szakaszok védelme Up: A STREAMS driverek Previous: Mire kell vigyázni

STREAMS szolgáltatások

A STREAMS driverekben a driver megnyitását, az adatok továbbítását és a driver lezárását más-más eljárás végzi. Ezeket az eljárásokat a kernel a neki átadott táblázatok alapján tudja elérni, és amikor végrehajtja oket, akkor paraméterként átad az eljárásoknak információkat, ami megkönnyíti a munkájukat. A leggyakrabban használt rutinok és feladatuk leírása a következo pontok témája.
Általában külön eljárásokat írhatunk a lefelé és a felfelé haladó streamhez, de írhatunk a két stream által közösen használt rutint is. Ha valamelyik szolgáltatásra nincs szükség, akkor azt nem kell kódolni (ld. késobb).

--- - Driver/modul megnyitása (open) - ---

  Szintaxis :

  int xxopen(queue_ptr,dev,flag,sflag)
  queue_t *queue_ptr;  /* A read-queuera a pointer */
  dev_t dev;
  int flag,sflag;
Ez a rutin STREAMS drivereknél a driver megnyitásánál, a STREAMS moduloknál a modulra vonatkozó I_PUSH hívásnál lesz végrehajtva. A hagyományos UNIX device driverekhez hasonlóan ennek az eljárásnak inicializálási feladatai vannak. A queue_ptr paraméter az új streamre egy pointer. A dev paraméter a device numbert tartalmazza, a flag paraméter megegyezik a hagyományos UNIX device drivereknél használt flag-gel jelölt paraméterrel ( open flagek, ld. oflags az open rendszerhívás paraméterei között). A dev paraméter mind a major mind a minor device numbert tartalmazza. Ha szükségünk van ezek közül valamelyikre, akkor az a major() illetve minor() kernel segédrutinnal (legtöbb helyen ez egy makro) kinyerheto a dev paraméterbol. Az sflag a stream megnyitásának speciális jellemzoit tartalmazza. Értéke lehet : Az, hogy egy driver hogyan lesz megnyitva, vagyis az sflag= 0 lesz vagy sflag= CLONEOPEN lesz, az a /dev directoryban levo speciális filera utaló bejegyzés tartalmától függ. A clone-drivernek a major device numberja 63 legyen (SINIX rendszerben a clone driver major device numberja pont 63), a minor device numberje pedig legyen egyenlo az igazi device major device numberjével. Ettol függetlenül csinálhatunk még több directory-bejegyzést is a filerendszerbe az igazi driver saját major és minor device numberjeivel. Ezekkel az egyes minor device-okat direkt el tudjuk érni (ha például csak a kontroller 2. portja jó nekünk, akkor azt). Erre láthatunk példát a következo táblázatban.

Ha az xcln filet megnyitjuk, aminek a major device numberje egyenlo a clone driver major device numberjével, akkor a clone driver lesz eloször végrehajtva, és (mint egy diszpécser) keres egy üres minor devicet, és ezt adja tovább a driver open rutinnak. A megnyitó rutin egy nulla visszatérési értékkel jelzi, ha nem volt hiba a futása közben, vagy OPENFAIL értékkel térjen vissza, ha a megnyitás eredménytelen volt. Az open és a close rutinok végrehajtásakor a kernel lokkolja a device i-nodeját, így egyszerre csak egy open vagy close rutin lehet aktív major/minor deviceonként. Megjegyzés: Ha a felhasználói programokból megnyitjuk egy STREAMS device driver valamelyik minor device-ját, majd késobb ismét kiadunk egy open rednszerhívást ugyanarra a minor devicera, akkor a második open rendszerhívásnál az open rutin nem lesz újra meghívva.

--- - Driver/modul lezárása (close) - ---

  Szintaxis :

  xxclose(queue_ptr)
  queue_t *queue_ptr;  /* Pointer a read queuera */
A rutin a STREAMS driverre vonatkozó close rendszerhívásnál és az I_POP ioctl hívásnál lesz végrehajtva. Ezután a felhasználói program már nem tudja elérni a device drivert (vagy modult). Sikeres végrehajtás esetén a visszatérési érték: 0, sikertelen végrehajtás esetén pedig az errno változóba rakandó érték legyen. Megjegyzés: a close rutin csak akkor lesz meghívva, amikor az adott minor devicera vonatkozó legutolsó filet is lezárták.

--- - Üzenet fogadása (put rutin) - ---

  Szintaxis :

  int xxput(qp,mp)
  queue_t *qp;
  mblk_t *mp;
Ez az eljárás akkor lesz végrehajtva, amikor a drivernek (vagy modulnak) adatot kell fogadnia a qp paraméterében megadott streamrol. A mp paraméter a beérkezett üzenetre pointer. Az üzenetet vagy el kell dobnia, vagy módosítva tovább kell adnia. Ha továbbadja, akkor vagy egy saját sorába ( putq() függvénnyel), vagy a streamen levo következo modulnak ( putnext() makróval), vagy pedig az ellenkezo irányú sorba ( qreply() függvénnyel) adhatja tovább. Ha egy saját sorába adja tovább, akkor az üzenet még átmegy egy service rutinon is (ld. késobb). Az üzenettovábbítás általában az üzenetre mutató pointer továbbadását jelenti.

--- - A service rutin - ---

  Szintaxis :

  int xxsrv(qp)
  queue_t *qp;
A service rutin csak a saját sorára mutató pointert kapja meg paraméterként. A getq függvénnyel tudja a sorából a következo üzenetet megszerezni, majd ezután ha tudja, akkor továbbadhatja a streamen következo modulnak. Ez alapján egy service rutin vázlatos felépítése a következo lehet :
  int xxsrv(qp)
    queue_t *qp;
  {
    /* Lokalis deklaraciok - reentrans kod erdekeben */
    mblk_t *mp;

    while (mp=getq(qp) != NULL)
    {
      if (canput(qp->q_next) || (a message magas prioritasu))
      {
         dolgozd_fel_az_uzenetet();
         if (tovabb_kell_adni_az_uzenetet())
         {
           putnext(qp,mp);
         }
      } else {
         putbq(qp,mp);
         return;
      }           
    }
  }
Az üzenettípusok értékei úgy vannak kiosztva, hogy azok az üzenetek alacsony prioritásúak, amelyeknek adatblokkjában a db_type mezo értéke QPCTL-nél kisebb (a QPCTL makro a saját operációs rendszerünk valamelyik headerfile-jában van definiálva).

--- - Service rutin vs. put rutin - ---

A service rutin opcionális, csak akkor szükséges, ha a put rutin az üzenetet nem tudja a beérkezésének " pillanatában " rögtön feldolgozni (mert például a hardware periféria még nem ért el egy bizonyos belso állapotot) vagy a stream már túl van terhelve és nem fér bele az üzenet. Minden modulhoz és driverhez meg lehet adni egy low water mark és egy high water mark értéket. Ez azért jó, mert el lehet vele érni egy nagyjából egyenletes adatáramlást (nem alakul ki adatdugó). Ha az üzenetek által lefoglalt byte-ok száma meghaladja a modulhoz megadott high water mark értéket, akkor egy QFULL flag be lesz állítva. Ennek a flagnek az állapotát az elotte levo modul a canput kernelfüggvénnyel lekérdezheti, és ha a flag be van állítva, akkor normál (alacsony) prioritású üzeneteket már nem adhat tovább. (Ezeket a saját sorába visszarakhatja a putbq STREAMS kernel segédfüggvénnyel.) A service rutinra csak akkor jut a vezérlés, ha az addig üres sorba egy új üzenet került, vagy az alatta következo modulban elérte az üzenetek által lefoglalt byte-ok száma a low water markot. Ezen kívül máskor is megkaphatja a vezérlést, de errol saját magának kell gondoskodnia (a qenable és az enableok STREAMS kernel segédrutinok segítségével).

--- - Driver ioctl rutin - ---

A hagyományos karakteres UNIX device driverekben egy külön belépési pont az ioctl hívásokat feldolgozó eljárás. Ezzel szemben a STREAMS device driverek esetében az ioctl hívásokat többnyire a stream-fej dolgozza fel, azokból bizonyos típusú üzeneteket generál, ami le lesz küldve a STREAMS drivernek (vagy modulnak). Az I_STR hívás például arra utasítja a stream-fejet, hogy egy M_IOCTL típusú üzenetet küldjön le a streamen. Ekkor az ioctl hívások feldolgozása az M_IOCTL típusú üzenetek driveren belüli feldolgozását jelenti.



next up previous contents
Next: Kritikus szakaszok védelme Up: A STREAMS driverek Previous: Mire kell vigyázni



Csizmazia Balazs
Tue Apr 2 00:06:27 MET DST 1996