Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Figyelmeztetés
A Windows 11-ből a felhasználói mód ütemezése nem támogatott. Minden hívás meghiúsul a ERROR_NOT_SUPPORTEDhiba miatt.
A felhasználói módú ütemezés (UMS) egy egyszerű mechanizmus, amellyel az alkalmazások saját szálakat ütemezhetnek. Az alkalmazások felhasználói módban válthatnak az UMS-szálak között anélkül, hogy bevonnák a rendszerütemezőt, és visszanyerhetik a processzor irányítását, ha egy UMS-szál blokkolja a kernelt. Az UMS-szálak különböznek a szálaktól, mivel minden UMS-szálnak saját szálkörnyezete van, és nem osztanak meg egyetlen szálkörnyezetet. A felhasználói módban történő szálváltási képesség teszi az UMS-t hatékonyabbá, mint a szálkészleteket a rövid időtartamú, kevés rendszerhívást igénylő munkaelemek kezelésében.
Az UMS olyan nagy teljesítményigényű alkalmazásokhoz ajánlott, amelyek többszálas vagy többmagos rendszereken egyszerre több szálat kell egyszerre futtatniuk. Az UMS előnyeinek kihasználásához az alkalmazásnak implementálnia kell egy ütemező összetevőt, amely kezeli az alkalmazás UMS-szálait, és meghatározza, hogy mikor kell futtatni őket. A fejlesztőknek meg kell fontolniuk, hogy alkalmazásteljesítmény-követelményeik indokolják-e az ilyen összetevők fejlesztésében részt vevő munkát. A mérsékelt teljesítménykövetelményekkel rendelkező alkalmazások jobban kiszolgálhatók, ha lehetővé teszik a rendszerütemező számára a szálak ütemezését.
Az UMS a Windows 7 és a Windows Server 2008 R2 AMD64 és Itanium verzióján futó 64 bites alkalmazásokhoz érhető el a Windows 10 21H2 és a Windows Server 2022 rendszeren keresztül. Ez a funkció nem érhető el az Arm64, a Windows 32 bites verzióiban vagy a Windows 11-ben.
További részletekért tekintse meg a következő szakaszokat:
- UMS Ütemező
- UMS Ütemezőszál
- UMS dolgozószálak, szálkörnyezetek és befejezési listák
- UMS Scheduler belépési pont függvény
- UMS szál-végrehajtás
- UMS ajánlott eljárásai
UMS Scheduler
Az alkalmazás UMS-ütemezője feladata UMS-szálak létrehozása, kezelése és törlése, valamint annak meghatározása, hogy melyik UMS-szálat kell futtatni. Az alkalmazás ütemezője a következő feladatokat hajtja végre:
- Létrehoz egy UMS-ütemezőszálat minden olyan processzorhoz, amelyen az alkalmazás UMS-munkavégző szálakat fog futtatni.
- UMS-munkaszálakat hoz létre az alkalmazás munkájának elvégzéséhez.
- Saját, futtatásra kész munkaszál-üzenetsort tart fenn, és kiválasztja a futtatandó szálakat az alkalmazás ütemezési szabályzatai alapján.
- Létrehoz és figyel egy vagy több befejezési listát, ahol a rendszer a kernelben végzett feldolgozás befejezése után sorba állítja a szálakat. Ezek közé tartoznak az újonnan létrehozott feldolgozási szálak, valamint azok a szálak, amelyek korábban rendszerhívás során blokkolva voltak és most feloldódtak.
- Egy belépési pontként szolgáló ütemező függvényt biztosít a rendszertől érkező értesítések kezelésére. A rendszer meghívja a belépési pont függvényt, amikor egy ütemező szál létrejön, egy feldolgozószál egy rendszerhíváson blokkol, vagy egy feldolgozószál explicit módon adja át a vezérlést.
- Tisztítási feladatokat hajt végre a futó munkaszálak esetében.
- Az ütemező rendezett leállítását hajtja végre, amikor az alkalmazás kéri.
UMS Ütemező szál
Az UMS ütemezőszál egy olyan szokásos szál, amely az EnterUmsSchedulingMode függvény meghívásával vált át UMS-sé. A rendszerütemező meghatározza, hogy az UMS ütemezőszál mikor fut a többi kész szálhoz viszonyított prioritása alapján. A processzort, amelyen az ütemezőszál fut, a szál affinitása befolyásolja, ugyanaz, mint a nem UMS-szálak esetében.
Az EnterUmsSchedulingMode hívója egy befejezési listát és egy UmsSchedulerProc belépési pont függvényt határoz meg az UMS ütemezőszálhoz való társításához. A rendszer meghívja a megadott belépési pont funkciót, amikor befejeződött a hívószál UMS-vé alakítása. Az ütemező belépési pont függvénye felelős a megadott szál megfelelő következő műveletének meghatározásáért. További információért lásd a későbbiekben ebben a témakörben a UMS Scheduler Entry Point Function-t.
Az alkalmazások létrehozhatnak egy UMS-ütemezőszálat minden olyan processzorhoz, amelyet UMS-szálak futtatására fognak használni. Előfordulhat, hogy az alkalmazás beállítja az egyes UMS-ütemezőszálak affinitását egy adott logikai processzorhoz, amely általában kizárja a nem kapcsolódó szálak futtatását a processzoron, és hatékonyan fenntartja azt az adott ütemezőszálhoz. Vegye figyelembe, hogy a szál affinitásának ily módon történő beállítása hatással lehet a rendszer általános teljesítményére azáltal, hogy más, a rendszeren futó folyamatokat éheztet. További információ a szál affinitásáról: Több processzoros.
UMS-munkaszálak, szálkörnyezetek és befejezési listák
Az UMS-feldolgozói szál úgy jön létre, hogy meghívja a CreateRemoteThreadEx függvényt a PROC_THREAD_ATTRIBUTE_UMS_THREAD attribútummal, megadva egy UMS-szálkörnyezetet és egy befejezési listát.
Az UMS-szálak környezete egy feldolgozó szál UMS-szálállapotát jelöli, és a munkaszál azonosítására szolgál az UMS-függvényhívásokban. Létrejön a CreateUmsThreadContextmeghívásával.
A befejezési lista a CreateUmsCompletionList függvény meghívásával jön létre. A befejezési listák olyan UMS-feldolgozószálakat kapnak, amelyek befejezték a végrehajtást a kernelben, és készen állnak a felhasználói módban való futtatásra. Csak a rendszer képes sorba állítani a feldolgozói szálakat egy befejezési listára. Az új UMS munkaszálak automatikusan sorba kerülnek a szálak létrehozásakor megadott befejezési listán. A korábban blokkolt munkaszálak is bekerülnek a teljesítési listára, amint már nincsenek blokkolva.
Minden UMS-ütemezőszál egyetlen befejezési listához van társítva. Ugyanahhoz a befejezési listához azonban tetszőleges számú UMS ütemezőszál társítható, és egy ütemezőszál lekérheti az UMS-környezeteket minden olyan befejezési listából, amelyhez mutató tartozik.
Minden teljesítési listának van egy társított eseménye, amelyet a rendszer jelez, amikor egy vagy több feldolgozószálat egy üres listára helyez. A GetUmsCompletionListEvent függvény lekéri az esemény fogantyúját egy megadott befejezési listához. Egy alkalmazás több befejezési listaeseményre is várakozhat az alkalmazás számára érthető egyéb eseményekkel együtt.
UMS Ütemező belépési pont függvénye
Az alkalmazás ütemező belépési pont függvénye UmsSchedulerProc függvényként van implementálva. A rendszer a következő időpontokban hívja meg az alkalmazás ütemezőjének belépési pontként szolgáló függvényét:
- Amikor egy nem UMS-szál UMS ütemező szállá alakul át azáltal, hogy lehívja a EnterUmsSchedulingMode.
- Amikor egy UMS-munkaszál meghívja a(z) UmsThreadYieldfüggvényt.
- Ha egy UMS-feldolgozó szál blokkol egy rendszerszolgáltatást, például rendszerhívást vagy laphibát.
A UmsSchedulerProc függvény Ok paramétere határozza meg a belépési pont függvény meghívásának okát. Ha a belépési pont függvény meghívása egy új UMS ütemezőszál létrehozása miatt történt, a SchedulerParam paraméter az EnterUmsSchedulingModehívója által megadott adatokat tartalmazza. Ha a belépési pont függvény azért lett meghívva, mert umsthreadyield szálat eredményezett, a SchedulerParam paraméter a UmsThreadYieldhívója által megadott adatokat tartalmazza. Ha a belépési pont függvény azért lett meghívva, mert egy UMS-feldolgozó szál le van tiltva a kernelben, a SchedulerParam paraméter NULL.
Az ütemező belépési pont függvénye felelős a megadott szál megfelelő következő műveletének meghatározásáért. Ha például egy feldolgozószál le van tiltva, az ütemező belépési pont függvénye futtathatja a következő elérhető kész UMS-feldolgozó szálat.
Az ütemező belépési pont függvényének meghívásakor az alkalmazás ütemezőjének meg kell kísérelnie a kapcsolódó befejezési lista összes elemének lekérését a DequeueUmsCompletionListItems függvény meghívásával. Ez a függvény lekéri azon UMS-szálkörnyezetek listáját, amelyek befejezték a feldolgozást a kernelben, és készen állnak a felhasználói módban való futtatásra. Az alkalmazás ütemezője nem futtathat UMS-szálakat közvetlenül ebből a listából, mert ez kiszámíthatatlan viselkedést okozhat az alkalmazásban. Ehelyett az ütemezőnek le kell kérnie az összes UMS-szálkörnyezetet úgy, hogy meghívja a GetNextUmsListItem függvényt minden egyes környezethez, szúrja be az UMS-szál kontextusait az ütemező kész szál-üzenetsorába, és csak ezután futtassa az UMS-szálakat a kész szálsorból.
Ha az ütemezőnek nem kell több eseményre várnia, akkor a DequeueUmsCompletionListItems függvényt nem nulla időtúllépéssel kell meghívnia, hogy a függvény a visszatérés előtt az elkészítési lista eseményére várjon. Ha az ütemezőnek több befejezési listaeseményre is várnia kell, akkor a DequeueUmsCompletionListItems kell meghívnia nullás időtúllépési paraméterrel, így a függvény azonnal visszatér, még akkor is, ha a befejezési lista üres. Ebben az esetben az ütemező explicit módon várakozhat a befejezési lista eseményein, például WaitForMultipleObjectshasználatával.
UMS-szál végrehajtása
Az újonnan létrehozott UMS munkaszál a megadott befejezési listára kerül, és csak akkor indul el, ha az alkalmazás UMS-ütemezője kiválasztja a futtatáshoz. Ez eltér a nem UMS-szálaktól, amelyek futtatását a rendszerütemező automatikusan ütemezi, kivéve, ha a hívó kifejezetten felfüggeszti a szálat.
Az ütemező a munkaszál futtatásához meghívja a ExecuteUmsThread-t a munkaszál UMS-környezetével. Az UMS-munkaszál addig fut, amíg az UmsThreadYield függvényt hívja, blokkol, vagy leáll.
Az UMS ajánlott eljárásai
Az UMS-t megvalósító alkalmazásoknak az alábbi ajánlott eljárásokat kell követniük:
- Az UMS-szálkörnyezetek mögöttes struktúráit a rendszer felügyeli, és nem szabad közvetlenül módosítani. Ehelyett QueryUmsThreadInformation és SetUmsThreadInformation használatával kérje le és állítsa be az UMS-feldolgozó szál adatait.
- A holtpontok elkerülése érdekében az UMS ütemezőszál nem oszthatja meg a zárolásokat az UMS-munkavégző szálakkal. Ide tartoznak az alkalmazás által létrehozott zárolások és a rendszerzárolások is, amelyeket közvetve olyan műveletek szereznek be, mint például a halomból való kiosztás vagy a DLL-ek betöltése. Tegyük fel például, hogy az ütemező egy DLL-t betöltő UMS-feldolgozó szálat futtat. A feldolgozó szál megszerzi a betöltő zárat és blokkol. A rendszer meghívja az ütemező belépési pont függvényét, amely betölt egy DLL-t. Ez holtpontot okoz, mert a rakodó zárolása már meg van tartva, és csak az első szál feloldása után oldható fel. A probléma elkerülése érdekében delegáljon olyan munkát, amely zárolásokat oszthat meg az UMS-munkaszálakkal egy dedikált UMS-munkaszálra vagy egy nem UMS-szálra.
- Az UMS akkor a leghatékonyabb, ha a legtöbb feldolgozás felhasználói módban történik. Amikor csak lehetséges, kerülje a rendszerhívásokat UMS-munkaszálakban.
- Az UMS-munkaszálaknak nem szabad feltételezniük, hogy a rendszerütemezőt használják. Ennek a feltételezésnek lehetnek finom hatásai; Ha például az ismeretlen kód egyik szála beállít egy szál prioritást vagy affinitást, az UMS-ütemező továbbra is felülbírálhatja azt. Előfordulhat, hogy a rendszerütemező használatát feltételező kód nem a várt módon működik, és egy UMS-szál meghívásakor megszakadhat.
- Előfordulhat, hogy a rendszernek zárolnia kell egy UMS munkaszál szálkörnyezetét. Egy kernelmódú aszinkron eljáráshívás (APC) például megváltoztathatja az UMS-szál környezetét, ezért a szálkörnyezetnek zárolva kell lennie. Ha az ütemező megpróbálja végrehajtani az UMS szálkörnyezetet, miközben az zárolva van, a hívás sikertelen lesz. Ez a viselkedés tervezés alapján történik, és az ütemezőt úgy kell megtervezni, hogy újra megpróbáljon hozzáférni az UMS-szál környezetéhez.