 
    
    
    
      
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 :

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.
 
 
    
    
   