Megosztás:


Rendszermunkaszálak

A késleltetett feldolgozást igénylő illesztőprogramok használhatnak munkaelemet, amely a tényleges feldolgozást végző illesztőprogram-visszahívási rutinra mutató mutatót tartalmaz. Az illesztőprogram várólistára állítja a munkaelemet, a rendszermunkaszál pedig eltávolítja a munkaelemet az üzenetsorból, és futtatja az illesztőprogram visszahívási rutinját. A rendszer ezeknek a rendszermunkaszálaknak a készletét tartja fenn, amelyek olyan rendszerszálak, amelyek mindegyike egyszerre egy munkaelemet dolgoz fel.

Az illesztőprogram a WorkItem visszahívási rutint társítja a munkaelemhez. Amikor a rendszermunkaszál feldolgozza a munkaelemet, meghívja a társított WorkItem rutint . A Windows Vista és a Windows újabb verzióiban az illesztő ehelyett egy WorkItemEx rutint társíthat egy munkaelemhez. A WorkItemEx olyan paramétereket vesz fel, amelyek eltérnek a WorkItem által megadott paraméterektől.

A WorkItem és a WorkItemEx rutinok rendszerszál-környezetben futnak. Ha egy illesztőprogram-küldési rutin futtatható felhasználói módban, akkor ez a rutin meghívhat egy WorkItem vagy WorkItemEx rutint minden olyan művelet végrehajtásához, amely rendszerszál-környezetet igényel.

Munkaelem használatához az illesztőprogram a következő lépéseket hajtja végre:

  1. Új munkaelem lefoglalása és inicializálása.

    A rendszer egy IO_WORKITEM struktúrát használ egy munkaelem tárolásához. Ha új IO_WORKITEM struktúrát szeretne lefoglalni és munkaelemként inicializálni, az illesztőprogram meghívhatja az IoAllocateWorkItemet. A Windows Vista és a Windows újabb verzióiban az illesztőprogram másik lehetőségként lefoglalhatja a saját IO_WORKITEM struktúráját, és meghívhatja az IoInitializeWorkItem parancsot a struktúra munkaelemként való inicializálásához. (Az illesztőnek meg kell hívnia az IoSizeofWorkItemet a munkaelem tárolásához szükséges bájtok számának meghatározásához.)

  2. Rendelje hozzá a visszahívási rutint a munkaelemhez, és várólistára helyezze a munkaelemet, hogy egy rendszermunkaszál dolgozza fel.

    Ha egy WorkItem-rutint szeretne társítani a munkaelemhez, és várólistára szeretné helyezni a munkaelemet, az illesztőnek meg kell hívnia az IoQueueWorkItemet. Ha ehelyett egy WorkItemEx rutint szeretne társítani a munkaelemhez, és várólistára szeretné helyezni a munkaelemet, az illesztőnek meg kell hívnia az IoQueueWorkItemEx-et.

  3. Miután a munkaelemre már nincs szükség, szabadítsd fel.

    Az IoAllocateWorkItem által lefoglalt munkaelemet az IoFreeWorkItem szabadíthatja fel. Az IoInitializeWorkItem által inicializált munkaelemet az IoUninitializeWorkItem-nek nem kell inicializálnia, mielőtt felszabadítható lenne.

    A munkaelem csak akkor lehet inicializálatlan vagy felszabadítva, ha a munkaelem jelenleg nincs sorban. A rendszer lekérdezi a munkaelemet, mielőtt meghívja a munkaelem visszahívási rutinját, így az IoFreeWorkItem és az IoUninitializeWorkItem meghívható a visszahívásból.

A hosszadalmas feldolgozást igénylő vagy blokkoló hívást kezdeményező DPC-nek a feladat feldolgozását egy vagy több munkaelemre kell delegálnia. A DPC futtatása alatt minden szál futása meg van akadályozva. Ezenkívül az IRQL = DISPATCH_LEVEL címen futó DPC nem kezdeményezheti a blokkoló hívásokat. A munkaelemeket feldolgozó rendszermunkaszál azonban az IRQL = PASSIVE_LEVEL értéken fut. Így a munkaelem tartalmazhat blokkoló hívásokat. A rendszermunkaszálak például várakozhatnak egy diszpécserobjektumon.

Mivel a rendszermunkaszálak készlete korlátozott erőforrás, a WorkItem és a WorkItemEx rutinok csak rövid ideig tartó műveletekhez használhatók. Ha ezen rutinok egyike túl hosszú ideig fut (ha például határozatlan ciklust tartalmaz), vagy túl sokáig vár, a rendszer holtpontra tud férni. Ezért ha egy illesztőprogram hosszú ideig késleltetett feldolgozást igényel, akkor inkább a PsCreateSystemThread meghívásával hozza létre saját rendszerszálát.

Ne hívja meg az IoQueueWorkItem vagy az IoQueueWorkItemEx parancsot az üzenetsorban már szereplő munkaelem várólistára helyezéséhez. Ez a rendszeradat-struktúrák sérülését okozhatja. Ha az illesztőprogram minden egyes illesztőprogram-rutin futtatásakor ugyanazt a munkaelemet várólistára állítja, az alábbi technikával elkerülheti a munkaelem második sorban állását, ha már szerepel az üzenetsorban:

  • Az illesztőprogram fenntartja a munkavégző rutin feladatainak listáját.
  • Ez a feladatlista a munkavégző rutinnak adott környezetben érhető el. A munkavégző rutin és a feladatlistát módosító illesztőprogram-rutinok szinkronizálják a hozzáférésüket a listához.
  • A munkavégző rutin minden futtatásakor végrehajtja a listában szereplő összes feladatot, és eltávolítja az egyes feladatokat a listáról a tevékenység befejezésekor.
  • Amikor új feladat érkezik, az illesztőprogram hozzáadja ezt a feladatot a listához. Az illesztőprogram csak akkor várólistára állítja a munkaelemet, ha a feladatlista korábban üres volt.

A rendszer feldolgozószála eltávolítja a munkaelemet az üzenetsorból, mielőtt meghívja a munkaszálat. Így egy meghajtószál biztonságosan újra sorba állíthatja a munkaelemet, amint a munkaszál elkezd futni.