Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка С_Р 2 частина.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.3 Mб
Скачать

Урок № 90

(згідно навчальної робочої програми)

Тема: «Керування потоками у Windows ХР»

Питання:

  1. Складові елементи потоку.

  2. Структури даних потоку.

  3. Створення потоків.

  4. Особливості програмного інтерфейсу потоків.

Для того щоб виконувати код, у рамках процесу обов’язково необхідно створити потік. Процеси і потоки є різними сутностями в системі, що перебувають у чітко визна­ченому взаємозв’язку один з одним; для роботи з ними використовують різні системні виклики.

БагатопотоковістьWindowsХР базується на схемі 1:1. Кожному потоку кори­стувача відповідає сутність у ядрі, при цьому ядро відповідає за планування пото­ків. Процеси не плануються.

Складові елементи потоку

Потік у WindowsХР складається з таких елементів:

  • вмісту набору регістрів, який визначає стан процесора;

  • двох стеків — один використовують для роботи в режимі користувача, ін­ший — у режимі ядра; ці стеки розміщені в адресному просторі процесу, що створив цей потік;

  • локальної пам’яті потоку (TLS);

  • унікального ідентифікатора потоку (threadid, tid), який вибирають із того са­мого простору імен, що й ідентифікатори процесів.

Сукупність стану процесора, стеків і локальної пам’яті потоку становить кон­текст потоку. Кожний потік має власний контекст. Усі інші ресурси процесу спільно використовуються потоками.

Розрізняють два види потоків: потоки користувача і потоки ядра, які у Win­dows ХР називають системними робочими потоками — system worker threads. Перші з них створюють у режимі користувача й тільки за необхідності перемика­ють у режим ядра. Інші створюють в ядрі під час його ініціалізації і виконують у режимі ядра протягом усього часу їхнього існування.

Структури даних потоку

Для виконавчої системи WindowsХР кожен потік відоб­ражається об’єктом-потоком виконавчої системи(executivethreadobject), який та­кож називають керуючим блоком потоку(executivethreadblock, ETHREAD). Для ядра системи потік відображається об’єктом-потоком ядра (kernelthreadobject), який також називають блоком потоку ядра(threadkernelblock, KTHREAD).

У режимі користувача доступним є блок оточення потоку(threadenvironmentblock, ТЕВ), який перебуває в адресному просторі процесу, що створив потік.

Неважко помітити, що кожній структурі даних потоку відповідає структура даних процесу (блоки EPROCESS, KPR0CESSі РЕВ).

Керуючий блок потоку містить базову інформацію про потік, зокрема:

  • блок потоку ядра;

  • ідентифікатор процесу, до якого належить потік, і покажчик на керуючий блок цього процесу (EPROCESS);

  • стартову адресу потоку, з якої почнеться виконання його коду;

  • інформацію для підсистеми безпеки.

Блок потоку ядра, у свою чергу, містить інформацію, необхідну ядру для орга­нізації планування і синхронізації потоків, зокрема:

  • покажчик на стек ядра;

  • інформацію для планувальника;

  • інформацію, необхідну для синхронізації цього потоку;

  • покажчик на блок оточення потоку.

Блок оточення потоку містить інформацію про потік, доступну для застосу­вань режиму користувача. До неї належать:

  • ідентифікатор потоку;

  • покажчик на стек режиму користувача;

  • покажчик на блок оточення процесу, до якого належить потік;

  • покажчик на локальну пам’ять потоку.

Створення потоків

Основним засобом створення потоків у WindowsХР є функція CreateThread() Win32 АРІ. Назвемо етапи виконання цієї функції.

  1. В адресному просторі процесу створюють стек режиму користувача для потоку.

  2. Ініціалізують апаратний контекст потоку (у процесор завантажують дані, що визначають його стан). Цей крок залежить від архітектури процесора.

  3. Створюють об’єкт-потік виконавчої системи у призупиненому стані, для чого в режимі ядра:

створюють та ініціалізують структури даних потоку (блоки ETHREAD, KTHREAD, ТЕВ);

б) задають стартову адресу потоку (використовуючи передану як параметр адресу процедури потоку);

в) задають інформацію для підсистеми безпеки та ідентифікатор потоку;

виділяють місце під стек потоку ядра.

  1. Підсистемі Win32 повідомляють про створення нового потоку.

  2. Дескриптор та ідентифікатор потоку повертають у процес, що ініціював ство­рення потоку (викликав CreateThread()).

  3. Починають виконання потоку (виконують перехід за стартовою адресою).

Особливості програмного інтерфейсу потоків

Програмний інтерфейс керування потоками у WindowsХР є частиною Win32 АРІ. Такий інтерфейс ще називають інтерфейсом потоків Win32.

Створення потоків у Win32 АРІ

У Win32 АРІ, як зазначалося раніше, для створення потоку призначена функція CreateThreadO, а для його завершення - EndThreadO.

На практиці, однак, пару CreateThread( )/EndThread() є сенс використати лише тоді, коли з коду, що виконує потік, не викликаються функції стандартної бібліо­теки мови С (такі, як printfOабо strcmpO).

Річ у тому, що функції стандартної бібліотеки С у Win32 АРІ не пристосовані до використання за умов багатопотоковості, і для того щоб підготувати потік до роботи за таких умов, необхідно під час його створення і завершення виконувати деякі додаткові дії. Ці дії враховані у спеціальних бібліотечних функціях роботи з потоками, описаних у заголовному файлі process. h. Це функція _beginthreadex() для створення потоку й _endthreadex() — для завершення потоку.

Розглянемо синтаксис функції beginthreadex(). Відразу ж наголосимо, що той самий набір параметрів (відмінний лише за типами) передають і у функцію CreateThread().

#inc1ude <process.h>

unsigned long _beginthreadex( void *security. unsigned stack_size, unsigned WINAPI (*thread_fun)(void *). void *argument, unsigned init_state. unsigned *tid );

де: security — атрибути безпеки цього потоку (NULL— атрибути безпеки за замов­чуванням);

stack_size- розмір стека для потоку;

thread_fun- покажчик на функцію потоку;

argument— додаткові дані для передачі у функцію потоку;

іnit_state— початковий стан потоку під час створення (0 для потоку, що поч­не виконуватися негайно, CREATE_SUSPEND для припиненого);

tid— покажчик на змінну, в яку буде записано ідентифікатор потоку після ви­клику (0, якщо цей ідентифікатор не потрібний).

Функція _beginthreadex() повертає дескриптор створеного потоку, який по­трібно перетворити в тип HANDLE:

HANDLE th= (HANDLE)_beginthreadex( ... );

Після отримання дескриптора, якщо він у цій функції більше не потрібний, його закривають за допомогою CloseHandlе() аналогічно до дескриптора процесу:

Завершення потоків у Win32 API

Функцію потоку можна завершити двома способами.

  1. Виконати у ній звичайний оператор return(цей спосіб є найнадійнішим):

unsigned WINAPI thread_fun (void *num) { return 0:

}

  1. Викликати функцію _endthreadex() з параметром, що дорівнює коду повернення:

unsigned WINAPI thread_fun (void *num) {

_endthreadex(0);

}

Контрольні питання:

  1. Які складові елементи потоку?

  2. Яка структура даних потоку?

  3. Які основні етапи створення потоків?

  4. Як здійснюється створення потоків у Win32 АРІ?

  1. Як здійснюється завершення потоків у Win32 API?

Література: Шеховцов В.А. Операційні системи. – К.: Видавнича група BHV, 2005. – 576 с.: іл., стор. 82-87.