Необхідність у створенні робочих потоків - студопедія

Будь виконуваний код, як і код драйвера, працює в контексті деякого потоку. Ми поки не обговорювали способи, за допомогою яких драйвер може створити власний потік, тому передбачається, що потік, в якому виконується код драйвера, належить деякій прикладній програмі. Це означає, що прикладна програма створила такий потік для виконання свого коду, а не коду нашого драйвера. Якщо код драйвера виробляє тривалу обробку, або драйвер використовує механізм синхронізації з очікуванням звільнення деякого ресурсу, код прикладної програми, для виконання якого і створювався потік, не виконується. Якщо цей потік єдиний в прикладному процесі, то прикладна програма "висить".

Якщо описана ситуація має місце в диспетчерській функції драйвера верхнього рівня, ми "всього лише" "підвісили" прикладну програму, безпосередньо взаємодіє з драйвером. В цьому випадку прикладна програма знає про таку можливість, і може помістити операції взаємодії з драйвером (читання, запис, відправка кодів управління) в окремий потік. В цьому випадку драйвер може не турбуватися про прикладну програму. Однак, така ситуація досить рідкісна. Дуже часто код драйвера працює в контексті випадкового потоку, тобто будь-якого довільного потоку в системі. Такий потік нічого не знає про наш драйвер і вищеописана ситуація є неприйнятною. В цьому випадку драйвер повинен створити свій власний потік, в якому і виробляти тривалу обробку або очікування звільнення ресурсів.

Можлива інша ситуація, що вимагає обов'язкового створення потоків - коли драйверу необхідно виконати операції на рівні IRQL = DISPATCH_LEVEL).

[12.2] Системні робочі потоки (System Worker Thread WorkItems)

В процесі системної ініціалізації NT створює кілька потоків в процесі System. Ці потоки служать виключно для виконання роботи, яку він вимагає іншими потоками. Такі потоки найбільш зручні у випадках, коли потоку з підвищеним рівнем IRQL потрібно виконати роботу на рівні IRQL PASSIVE_LEVEL.

В принципі, можна створити новий потік, проте створення нового потоку і його планування планувальником є ​​більш ресурсоємним, ніж використання існуючого потоку. Більшість стандартних компонент ОС, таких як компоненти файлової системи, використовують для своїх потреб готові системні робочі потоки.

Є ситуації, при яких використання системних робочих потоків неприйнятно в силу їх організації. Такими ситуаціями є необхідність в тривалій (кілька сотень мікросекунд) обробці всередині потоку, або тривале очікування звільнення ресурсу або настання події. У цих ситуаціях драйвер повинен створювати свій власний потік.

Існує 3 типи системних робочих потоків: Delayed (уповільнені), Critical (критичні) і HyperCritical (сверхкритические). Всі типи потоків створюються на рівні IRQL PASSIVE_LEVEL. Для кожного типу потоків будуть різні:

· Число потоків даного типу

· Базовий пріоритет планування потоку, що відноситься до даного типу

· Чергу робочих елементів

Число потоків кожного типу залежить від обсягу пам'яті і типу ОС. У таблиці 1 вказано число потоків і базовий пріоритет планування для ОС Win2K Professional і Server.

Таблиця 1.Чісло Системних Робочих Потоків

Тип робочого потоку

Слід зазначити, що використання єдиного потоку типу HyperCritical не задокументовані. ОС використовує цей потік для виконання функції - чистильника, яка звільняє потоки при їх завершення.

При постановці робочого елемента в чергу вказується тип потоку, якій призначений робочий елемент.

Для роботи з системними робочими потоками існує 2 набори функцій - функції з префіксом Ex. і функції з префіксом Io. Функції з префіксом Ex використовувалися в ОС NT 4.0 і раніших версіях, і в Win2K вважаються застарілими.

У будь-якому випадку, спочатку драйвер повинен ініціалізувати робочий елемент за допомогою функцій ExInitializeWorkItem () або IoAllocateWorkItem (), помістити робочий елемент в чергу за допомогою функцій ExQueueWorkItem () або IoQueueWorkItem (), а при запуску функції, зазначеної в робочому елементі, ця функція зобов'язана звільнити займані робочим елементом ресурси за допомогою функцій ExFreePool () або IoFreeWorkItem ().