next up previous contents
Next: Általánosan használható kernel Up: A kernel segédrutinjai Previous: A kernel segédrutinjai

STREAMS-specifikus hívások

Az ebben a fejezetben ismertetett kernel rutinokat kizárólag STREAMS device driverekben használjuk. Részben azért, mert csak a STREAMS queuekon tudunk velük dolgozni, részben pedig azért, hogy STREAMS driverjeink és moduljaink hordozhatóak legyenek.

--- - allocb - lefoglal egy üzenetblokkot - ---

struct msgb *
    allocb(size)
    register int size;
Ez a függvény lefoglal egy üzenetblokkot a STREAMS adatterületen, amelynek a mérete legalább size byte. Az üzenet típusa M_DATA lesz (ezt a programban késobb meg lehet változtatni). Ha nincs elég memória, akkor az eredmény egy NULL pointer.

--- - bufcall - hívj meg egy eljárást, ha lesz szabad memória - ---

int bufcall(size, func, arg)
    int size;
    void (*func)();
    long arg;
Ezzel az eljárással lehet kérni a kerneltol például egy sikertelen allocb() hívás után, hogy ha felszabadul egy legalább size méretu memóriaterület (STREAMS üzenetek számára), akkor hívja meg a func paraméterben megadott függvényt arg paraméterrel (ez a (*func)(arg); függvényhívást jelenti majd). Ha a kernel a kérésünket tudomásul vette, akkor a függvény visszatérési értéke 1 lesz, ha ezt a kérésünket visszautasította, akkor 0 lesz a függvény visszatérési értéke.
FONTOS: Ha a megadott eljárást a kernel késobb majd meghívja, akkor sem lesz garantálva az, hogy az allocb() hívással tudunk egy megadott méretu területet lefoglalni, ugyanis a kernelben másoknak is szükségük lehet memóriára, és lehet például az, hogy az épp felszabadult memóriát egy nagyobb prioritású driver lefoglalja elolünk.
Megjegyzés: nagyon gondoljuk meg, hogy mikor használjuk ezt a kernel rutint, mert ezt a hívási igényt a Release 3.2 UNIX rendszerekben még nem tudjuk visszamondani. A veszély abban van, hogy eloállhat az a helyzet, hogy egy STREAMS deviceot már lezártunk, esetleg a queueja már más devicenak le lett foglalva, és csak ezután lesz valamikor meghívva a megadott függvény ...
Ezt a hiányosságot az ATT is észrevette, ezért a Release 4.0 UNIX rendszerben már van az unbufcall() kernel rutin, amellyel egy korábban bejegyzett és a kernel által elfogadott bufcall() hívás hatástalanítható.

--- - canput - van-e elég hely a streamben - ---

int canput(q)
    register queue_t *q;
Ez a függvény ellenorzi, hogy van-e még hely a q message queueban. Ha a q queuenak nincs service rutinja, akkor a canput() függvény megkeresi az adott streamen soron következo legelso olyan modult, amelynek van service rutinja. (Ha nem talál ilyen modult, akkor a keresés a stream végén fejezodik be.) Végül ha még fér valami a q queueba, akkor a függvény visszatérési értéke: 1 - ekkor lehet újabb üzenetet rakni a queuera, ha a queue betelt, akkor pedig 0 a visszatérési érték, és ekkor a hívó blokkolva lesz. (A blokkolás azt jelenti, hogy nem kerül rá a futásra kész service folyamatok listájára.)

--- - enableok - egy eddig inaktiv queue aktivizálása - ---

void enableok(q)
     queue_t *q;
A feladata egy korábban kiadott noenable() függvény hatástalanítása, ami arra utasította a task schedulert, hogy a q queuet iktassa ki. (Ez nem jelenti azt, hogy a qenable() kernel függvényhez hasonlóan a sor service rutinja egybol végre is lesz hajtva!)

--- - flushq - flush muvelet egy queuen - ---

void flushq(q,flag)
     register queue_t *q;
     int flag;
Ez a függvény töröl minden messaget a megadott q queueból, és felszabadítja az üzenetek által lefoglalt területet a freemsg() függvénnyel. A flag paraméter értéke, és ezek hatása (ld. <sys/stream.h> include filet) :

--- - freeb - egy darab üzenetblokk felszámolása - ---

void freeb(bp)
     register struct msgb *bp;
A freeb függvény felszabadítja a bp pointer által mutatott üzenetblokk által lefoglalt memóriaterületet, a hozzá tartozó adatblokkal együtt. (Ha a hozzá tartozó az adatblokk db_ref részének értéke 1-nél nagyobb, akkor csak ez a számláló fog csökkenni, a lefoglalt adatterület nem lesz felszabadítva.)

--- - freemsg - egy teljes üzenet felszámolása - ---

void freemsg(bp)
     register mblk_t *bp;
Végigmegy a megadott message minden egyes üzenetblokkján, és felszabadítja (ha lehet) a message által lefoglalt teljes memóriaterületet. Ha ez nem lehet (mert az adatblokk db_ref részének értéke 1-nél nagyobb), akkor ez a számláló eggyel csökkenni fog. (A freemsg() függvény végigmegy a message minden egyes blokkján, és minden egyes blokkot felszabadít a freeb() segítségével.)

--- - getmid - modul id. lekérdezése - ---

ushort getmid(name)
       char *name;
A függvény eredménye a megadott nevu modul modul azonosító száma. (Ha nincs ilyen modul, akkor az eredmény: 0).

--- - getq - következo message leszedése a queueról - ---

mblk_t *getq(q)
       register queue_t *q;
Leszedi a következo üzenetet (ha van) a q message queueról. A függvény egy pointert ad vissza, ami a leszedett message címét tartalmazza. Ha nincs már message a queuen, akkor a függvény visszatérési értéke NULL pointer lesz, és a rendszer beállít a queue adatstrukturájában egy QWANTR flaget, ami azt jelzi, hogy a queueról olvasni akarnak. Ha ilyen állapotban egy üzenet érkezik a queuera, akkor a kernel a qenable() függvény meghívásával automatikusan újraindítja a service rutint.
Ha a getq() rutin leszedett egy üzenetet a q message queueról, és ezután a queuen levo üzenetek összhossza kisebb, mint a queuehoz megadott low water mark érték, és a queuera már próbáltak korábban új üzenetet rakni, de ez sikertelen volt, akkor a q queue mögötti sor service rutinja a qenable() függvény meghívásával újra el lesz indítva.

--- - noenable - queue inaktivizálása - ---

void noenable(q)
     queue_t *q;
A megadott q queuet inaktiv állapotba hozza - a STREAMS service scheduler nem adja ennek a sornak a service rutinjára többet a vezérlést. (Inverz muvelete: az enableok() függvény.)

--- - OTHERQ - megadja a queue párját - ---

#define OTHERQ(q)    ((q)->q_flag&QREADR? (q)+1 : (q)-1)
A makro eredménye a q queue párjára mutató pointer. (Ha a q a read queue, akkor az eredmény a hozzá tartozó write queuera mutató pointer; ha q egy write queuera pointer, akkor az eredmény a read queuera pointer.)

--- - putctl - kontroll-üzenet továbbítása - ---

int putctl(q, type)
    queue_t *q;
    int type;
A putctl() függvény lefoglal egy üzenet számára az allocb() kernelhívás segítségével memóriát, az üzenet típusát beállítja a type paraméterben megadottra, majd meghívja a q paraméter által mutatott queue put rutinját. A függvény visszatérési értéke 1, ha minden rendben ment. Nulla akkor lehet a visszatérési érték, ha a rendszer nem tudott lefoglalni az üzenetblokk számára memóriát, vagy a type paraméter értéke az M_DATA, M_PROTO, M_PCPROTO, vagy M_DELAY értékek egyike.

--- - putbq - üzenet visszarakása a sorba - ---

int *putbq(q, bp)
    register queue_t *q;
    register mblk_t *bp;
A putbq() függvény a bp által mutatott üzenetet visszarakja a q által mutatott queue elejére. (A queuban legelobbre kerülnek a magas prioritású üzenetek, a normál prioritású üzenetek pedig a magas prioritású üzenetek mögé, de a korábban már ott levo alacsony prioritású üzenetek elé kerülnek.) A service rutin soha ne rakjon vissza magas prioritású üzenetet a saját queuejába, mert ez végtelen ciklust eredményezne a kernelen belül!
Sikeres végrehajtás esetén a függvény visszatérési értéke: 1, sikertelen végrehajtás esetén a visszatérési érték 0 lesz.

--- - putnext - egy üzenetet a következo queuera rak - ---

#define putnext(q,mp) ((*(q)->q_next->q_qinfo->qi_putp)((q)->q_next,(mp)))
A putnext() egy makro, amely a q után közvetlenül következo queue put() rutinját hívja meg, és átadja neki az mp által mutatott üzenetet.

--- - putq - egy megadott üzenetet valamelyik queuera rakja - ---

int *putq(q, bp)
    register queue_t *q;
    register mblk_t *bp;
A putq() függvény a q paraméterben meghatározott queura átadja az mp által mutatott üzenetet.

--- - qenable - queue aktivizálása - ---

void qenable(q)
     register queue_t *q;
Ez a függvény a q paraméter által meghatározott sort a STREAMS schedulernek arra a listájára rakja, amely a futásra kész sorok adatait tartalmazza. Ez azt jelenti, hogy az adott queue service rutinja rövid idon belül újból futni fog.

--- - qreply - üzenet visszaküldése ellentétes irányban - ---

void *qreply(q, bp)
     register queue_t *q;
     mblk_t *bp;
Ez a függvény meghatározza a q queue párját (a lefele meno streamnek a párja a felfelé meno, ill. fordítva), és azon a putnext() makro muködéséhez hasonlóan visszaküldi a bp pointer által meghatározott üzenetet. Ezt a függvényt szokták használni az M_IOCTL üzenetekre küldendo válasz visszaküldésére.

--- - RD - megadja a read queuet - ---

#define RD(q)    ((q)-1)
A makro paramétere ( q) egy write queuera mutató pointer, eredménye pedig a q queue párjára (vagyis a read queuera) mutató pointer. Ez a muvelet azért ilyen egyszeru, mert a kernel a queuekat nem egyenként foglalja le, hanem párosával. Az alacsonyabb memóriacímen van a read queue, a magasabbon pedig a write queue.

--- - splstr - átállítja az interrupt prioritási szintet - ---

#define splstr()   spltty()
Az splstr() makro az spltty() kernelhívás segítségével beállítja a processzor interrupt prioritási szintjét a STREAMS driverek és modulok interrupt prioritási szintjére, a kritikus szakaszok védelme érdekében. Ez azt jelenti, hogy az éppen futó driver muködését más driverek vagy modulok nem tudják megszakítani. Ez a rutin visszatérési értékként az addigi processzor interrupt prioritási szintet adja. A kritikus szakasz végén az splx() kernelhívás segítségével vissza kell állítani a processzor interrupt prioritási szintjét az elozo értékre. Ezt a rutint csak igen indokolt esetben használjuk! Megjegyzés: az Intel 80386-os UNIX rendszerek esetén ez általában IPL=7 szintnek felel meg, és ekkor sem a soros vonalakról jövo megszakítások, sem az óramegszakítások nem lesznek megengedve. Mivel a rendszeróra is le lesz tiltva, ezért csak olyan rutinokat védjünk így, aminek a végrehajtása nem igényel több idot, mint két órainterrupt közti ido.

--- - unlinkb - egy üzenet elso blokkját törli - ---

mblk_t *
     unlinkb(bp)
     register mblk_t *bp;
Az unlinkb() függvény elválasztja a bp paraméter által mutatott üzenet elso üzenetblokkját a mögötte lévo blokkoktól, és egy pointert ad vissza az üzenet megmaradó részére. Az eredménye NULL pointer lesz, ha nem maradt több üzenetblokk az üzenetben. (Az elso üzenetblokk nem lesz automatikusan felszabadítva, így ez a programozó feladata marad.)

--- - WR - megadja a write queuet - ---

#define WR(q)    ((q)+1)
A WR makro paramétere ( q) egy read queuera mutató pointer, eredménye pedig a q queue párjára (vagyis a hozzá tartozó write queuera) mutató pointer.



next up previous contents
Next: Általánosan használható kernel Up: A kernel segédrutinjai Previous: A kernel segédrutinjai



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