Eszközsorok kezelése

Az I/O-kezelő általában (az FSD-k kivételével) létrehoz egy társított eszközsor-objektumot, amikor egy illesztőprogram meghívja az IoCreateDevice-t. IoStartPacket és IoStartNextPacket is biztosítva van, amelyeket az illesztőprogram meghívhat, hogy az I/O-kezelő az IRP-ket a társított eszközsorba illessze, vagy a StartIo-rutinjaikat meghívja.

Ezért ritkán szükséges (vagy különösen hasznos), hogy az illesztőprogram saját eszközsor-objektumokat hozzon létre az IRP-k számára. Valószínű, hogy a jelöltek olyan illesztőprogramok, mint például az SCSI-portillesztő, amelyeknek bizonyos számú szorosan összekapcsolt osztályillesztőből kell koordinálniuk a bejövő integrációs modulokat az egyetlen vezérlőn vagy buszadapteren keresztül szervizelt heterogén eszközökhöz.

Más szóval, a lemeztömbvezérlő illesztőprogramja nagyobb valószínűséggel használ egy illesztőprogram által létrehozott vezérlőobjektumot, mint hogy kiegészítő eszközsor-objektum(ok) beállítását végezze, míg a kiegészítő buszadapterhez és osztályillesztőkhöz tartozó illesztőprogramok valamivel nagyobb valószínűséggel használnak kiegészítő eszközsorokat.

Kiegészítő eszközsorok használata StartIo-rutinnal

Az IoStartPacket és az IoStartNextPacket meghívásával egy illesztőprogram Dispatch és DpcForIsr (vagy CustomDpc) rutinja szinkronizálja a hívásokat a StartIo rutinba az I/O-kezelő által az eszközobjektum létrehozásakor létrehozott eszközsor használatával. StartIo rutinnal rendelkező portillesztők esetén az IoStartPacket és IoStartNextPacket beillesztik és eltávolítják az IRP-ket az eszközsorban a portillesztő megosztott eszközvezérlőjéhez/adapteréhez. Ha a portillesztő kiegészítő eszközkészleteket állít be a szorosan összekapcsolt magasabb szintű osztály-illesztőktől érkező kérések tárolására, akkor a beérkező I/O kérési csomagokat ezekbe a kiegészítő eszközkészletekbe kell "rendeznie", általában a StartIo rutinjában.

A portillesztőnek meg kell állapítania, hogy az egyes IRP-k melyik póteszköz sorba tartoznak, mielőtt megpróbálná azokat a megfelelő sorba beszúrni. A céleszköz-objektumra mutató mutatót az IRP átadja az illesztőprogram dispatch rutinjának. Az illesztőnek mentenie kell a mutatót, hogy a bejövő IRP-k "rendezésében" használhassa. Vegye figyelembe, hogy a StartIo rutinnak átadott eszközobjektum-mutató az illesztőprogram saját eszközobjektuma, amely az eszközvezérlőt/adaptert jelöli, ezért erre a célra nem használható.

Az irP-k várólistára helyezése után az illesztőprogram a megosztott vezérlőt/adaptert a kérés végrehajtásához programozza. Így a portillesztő az összes eszköz bejövő kéréseit érkezési sorrendben tudja feldolgozni, amíg a KeInsertDeviceQueue hívása egy IRP-t nem helyez egy adott osztályillesztő eszközsorába.

Saját eszközsorát használva az összes IRP feldolgozásához a StartIo-rutinon keresztül, az alapszintű portillesztő sorosítja a műveleteket a megosztott eszköz (vagy busz) vezérlőn/adapteren keresztül az összes csatlakoztatott eszköz számára. Ha néha az integrációs modulokat az egyes támogatott eszközökhöz külön eszközsoron tartják, ez a portillesztő gátolja a már foglalt eszközök integrációs moduljainak feldolgozását, miközben növeli az I/O-átviteli sebességet minden más eszköz esetében, amely a megosztott hardveren keresztül végzi az I/O-t.

A portillesztő dispatch rutinjából az IoStartPacket hívására válaszul az I/O-kezelő vagy azonnal meghívja az illesztőprogram StartIo rutinját, vagy az IRP-t a portillesztő megosztott vezérlőjének/adapterének eszközobjektumához társított eszközsorba helyezi.

A portillesztőnek saját állapotinformációkat kell fenntartania a megosztott eszközvezérlőn/adapteren keresztül nyújtott heterogén eszközökről.

Az osztály-/portillesztők kiegészítő eszközsorokkal való tervezésekor tartsa szem előtt a következőket:

  • Az illesztőprogram nem tud könnyen mutatót kapni egy olyan eszközobjektumhoz, amelyet egy fölötte elhelyezkedő illesztőprogram hozott létre, kivéve az eszközverem tetején lévő eszközobjektumot.

    A kialakítás szerint az I/O-kezelő nem biztosít támogatási rutint egy ilyen mutató beszerzéséhez. Ezenkívül az illesztőprogramok betöltési sorrendje lehetetlenné teszi, hogy az alacsonyabb illesztőprogramok mutatót szerezzenek a magasabb szintű illesztőprogramok eszközobjektumaihoz, amelyek még nem lettek létrehozva, amikor egy alacsonyabb szintű illesztőprogram hozzáadja az eszközt.

    Bár az IoGetAttachedDeviceReference az illesztőprogram veremének legmagasabb szintű eszközobjektumára mutató mutatót ad vissza, az illesztőnek ezt a mutatót csak a verembe irányuló I/O-kérések célhelyének kijelölésére kell használnia. Az illesztőprogram nem kísérelheti meg az eszközobjektum olvasását vagy írását.

  • Az illesztőprogramok nem használhatnak mutatót egy olyan eszközobjektumra, amelyet egy olyan illesztőprogram hozott létre, amely fölötte rétegzett, kivéve, hogy kéréseket küld a saját eszközverem tetejére.

    Egyetlen eszközobjektumhoz (és annak eszközbővítményéhez) nem lehet többprocesszoros biztonságos módon szinkronizálni a hozzáférést két illesztőprogram között. Egyik illesztőprogram sem tehet feltételezéseket arról, hogy a másik illesztőprogram az adott pillanatban milyen I/O feldolgozást végez.

Még a szorosan összekapcsolt osztály-/portillesztők esetében is, minden osztályillesztőnek csak arra kell használnia a portillesztő eszközobjektumára mutató mutatót, hogy IRP-ket küldjön az IoCallDriver segítségével. Az alapul szolgáló portillesztőnek meg kell őriznie saját állapotát, valószínűleg a portillesztő eszközbővítményében, a szorosan összekapcsolt osztályillesztők eszközeivel kapcsolatos kérelmek kezelésére.

Kiegészítő eszközsorok kezelése illesztőprogram-rutinok között

Bármely portillesztő, amely IRP-ket sorol be kiegészítő eszközkiosztásokba egy szorosan összekapcsolt osztálymeghajtó-csoport számára, szintén hatékonyan kell kezelje az alábbi helyzetet:

  1. A dispatch rutinjai beszúrtak egy adott eszközre vonatkozó integrációs modulokat az eszköz illesztőprogram által létrehozott üzenetsorába.

  2. A többi eszköz IRP-kjei továbbra is érkeznek, sorba kerülnek az illesztő StartIo rutinjához az IoStartPacket segítségével, és a megosztott eszközvezérlőn keresztül lesznek feldolgozva.

  3. Az eszközvezérlő nem válik tétlenné, de az illesztőprogram által létrehozott eszközsorban tárolt minden egyes IRP-t a lehető leghamarabb várólistára kell helyezni az illesztőprogram StartIo rutinjára.

Következésképpen a portillesztő DpcForIsr rutinjának meg kell kísérelnie egy IRP átvitelét az adott eszköz belső eszközsorából a megosztott adapter/vezérlő eszközsorába, amikor a portillesztő befejez egy IRP-t, az alábbiak szerint:

  1. A DpcForIsr rutin meghívja az IoStartNextPacketet , hogy a StartIo rutin megkezdje a megosztott eszközvezérlőnek várólistára helyezett következő IRP feldolgozását.

  2. A DpcForIsr rutin meghívja a KeRemoveDeviceQueue-t , hogy törölje a következő IRP-t (ha van ilyen), amelyet a belső eszközsorában tart ahhoz az eszközhöz, amelynek nevében egy IRP-t szeretne végrehajtani.

  3. Ha a KeRemoveDeviceQueue nem NULL mutatót ad vissza, a DpcForIsr rutin meghívja az IoStartPacketet az egyszerűen lekérdezett IRP-vel, hogy várólistára helyezze a megosztott eszköz vezérlőjéhez/adapteréhez. Ellenkező esetben a KeRemoveDeviceQueue hívása egyszerűen alaphelyzetbe állítja az eszközsor-objektum állapotát Nem elfoglalt állapotra, és a DpcForIsr rutin kihagyja az IoStartPacket hívását.

  4. Ezután a DpcForIsr rutin meghívja az IoCompleteRequest függvényt a bemeneti IRP-vel, amelyhez a portillesztő éppen befejezte az I/O feldolgozást, vagy az I/O állapotblokkot hibával állítja be, vagy teljesíti az I/O kérést.

Vegye figyelembe, hogy az előző sorrend azt jelenti, hogy a DpcForIsr rutinnak azt az eszközt is meg kell határoznia, amelyhez az aktuális (bemeneti) IRP-t végrehajtja az IRP-k belső sorban állításának hatékony kezelése érdekében.

Ha a portillesztő megkísérli megvárni, amíg a megosztott vezérlője/adaptere tétlen lesz, mielőtt feldolgozza a kiegészítő eszközsorokban tárolt IRP-ket, az illesztőprogram esetleg megfoszthat egy olyan eszközt az erőforrásoktól, amelyhez nagy I/O-igény volt, miközben azonnal kiszolgál minden más eszközt, amelyhez az aktuális I/O-igény valójában sokkal kisebb volt.