close

Вход

Забыли?

вход по аккаунту

?

Практична робота №2

код для вставкиСкачать
Практична робота №2
Тема: Керування потоками у Windows XP
Мета: вивчити програмний інтерфейс керування потоками у Windows XP
Теоретичні відомості
1. Керування потоками у Windows ХР
Для того щоб виконувати код, у рамках процесу обов'язково необхідно створити потік. У системі Windows ХР реалізована модель потоків "у чистому вигляді". Процеси і потоки є різними сутностями в системі, що перебувають у чітко визначеному взаємозв'язку один з одним; для роботи з ними використовують різні системні виклики. У Windows ХР ніколи не використовували модель процесів, подібну до традиційної моделі UNIX.
Багатопотоковість Windows ХР базується на схемі 1:1. Кожному потоку користувача відповідає сутність у ядрі, при цьому ядро відповідає за планування потоків. Процеси не плануються.
1.1. Складові елементи потоку
Потік у Windows ХР складається з таких елементів:
* вмісту набору регістрів, який визначає стан процесора;
* двох стеків - один використовують для роботи в режимі користувача, інший - у режимі ядра; ці стеки розміщені в адресному просторі процесу, що створив цей потік;
* локальної пам'яті потоку (ТLS);
* унікального ідентифікатора потоку (thread id, tid), який вибирають із того самого простору імен, що й ідентифікатори процесів.
Сукупність стану процесора, стеків і локальної пам'яті потоку становить контекст потоку. Кожний потік має власний контекст. Усі інші ресурси процесу (його адресний простір, відкриті файли тощо) спільно використовуються потоками.
Розрізняють два види потоків: потоки користувача і потоки ядра, які у Windows ХР називають системними робочими потоками - system worker threads. Перші з них створюють у режимі користувача й тільки за необхідності перемикають у режим ядра. Інші створюють в ядрі під час його ініціалізації і виконують у режимі ядра протягом усього часу їхнього існування.
1.2. Структури даних потоку
Відображення потоків у системі, як і відображення процесів, засноване на об'єктній моделі Windows ХР. Для виконавчої системи Windows ХР кожен потік відображається об'єктом-потоком виконавчої системи (executive thread object), який також називають керуючим блоком потоку (executive thread block, ETHREAD). Для ядра системи потік відображається об'єктом-потоком ядра (kernel thread object), який також називають блоком потоку ядра (thread kernel block, KTHREAD).
У режимі користувача доступним є блок оточення потоку (thread environment block, TEB), який перебуває в адресному просторі процесу, що створив потік.
Неважко помітити, що кожній структурі даних потоку відповідає структура даних процесу (блоки EPROCESS, KPROCESS i PEB).
Керуючий блок потоку містить базову інформацію про потік, зокрема:
* блок потоку ядра;
* ідентифікатор процесу, до якого належить потік, і покажчик на керуючий блок цього процесу (ЕРRОСЕSS);
* стартову адресу потоку, з якої почнеться виконання його коду;
* інформацію для підсистеми безпеки.
Блок потоку ядра, у свою чергу, містить інформацію, необхідну ядру для організації планування і синхронізації потоків, зокрема:
* покажчик на стек ядра;
* інформацію для планувальника;
* інформацію, необхідну для синхронізації цього потоку;
* покажчик на блок оточення потоку.
Блок оточення потоку містить інформацію про потік, доступну для застосувань режиму користувача. До неї належать:
* ідентифікатор потоку;
* покажчик на стек режиму користувача;
* покажчик на блок оточення процесу, до якого належить потік;
* покажчик на локальну пам'ять потоку.
1.3. Створення потоків
Основним засобом створення потоків у Windows ХР є функція CreateThread() Win32 АРІ. Назвемо етапи виконання цієї функції.
1. В адресному просторі процесу створюють стек режиму користувача для потоку.
2. Ініціалізують апаратний контекст потоку (у процесор завантажують дані, що визначають його стан). Цей крок залежить від архітектури процесора.
3. Створюють об'єкт-потік виконавчої системи у призупиненому стані, для чого в режимі ядра:
a) створюють та ініціалізують структури даних потоку (блоки ЕТНRЕАD, КТНRЕАD, ТЕВ);
b) задають стартову адресу потоку (використовуючи передану як параметр адресу процедури потоку);
c) задають інформацію для підсистеми безпеки та ідентифікатор потоку;
d) виділяють місце під стек потоку ядра.
4. Підсистемі Win32 повідомляють про створення нового потоку.
5. Дескриптор та ідентифікатор потоку повертають у процес, що ініціював створення потоку (викликав CreateThread()).
6. Починають виконання потоку (виконують перехід за стартовою адресою).
1.4. Особливості програмного інтерфейсу потоків
Програмний інтерфейс керування потоками у Windows ХР є частиною Win32 АРІ. Такий інтерфейс ще називають інтерфейсом потоків Win32. Розглянемо особливості його використання.
Створення потоків у Win32 АРІ
У Win32 АРІ, як зазначалося раніше, для створення потоку призначена функція CreateThread(), а для його завершення - EndThread().
На практиці, однак, пару CreateThread()/EndThread() є сенс використати лише тоді, коли з коду, що виконує потік, не викликаються функції стандартної бібліотеки мови С (такі, як printf() aбo strcmp()).
Річ у тому, що функції стандартної бібліотеки С у Win32 АРІ не пристосовані до використання за умов багатопотоковості, і для того щоб підготувати потік до роботи за таких умов, необхідно під час його створення і завершення виконувати деякі додаткові дії. Ці дії враховані у спеціальних бібліотечних функціях роботи з потоками, описаних у заголовному файлі ргосеss.h. Це функція _beginthreadex() для створення потоку й _endthreadex() - для завершення потоку.
Розглянемо синтаксис функції _beginthreadex(). Відразу ж наголосимо, що той самий набір параметрів (відмінний лише за типами) передають і у функцію CreateThread().
#include <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 - розмір стека для потоку (зазвичай 0, у цьому разі розмір буде таким самим, що й у потоку, який викликає _beginthreadex());
thread_fun - покажчик на функцію потоку;
argument - додаткові дані для передачі у функцію потоку;
init_state - початковий стан потоку під час створення (0 для потоку, що почне виконуватися негайно, CREATE_SUSPEND для припиненого);
tid - покажчик на змінну, в яку буде записано ідентифікатор потоку після виклику (0, якщо цей ідентифікатор не потрібний).
Функція _beginthreadex() повертає дескриптор створеного потоку, який потрібно перетворити в тип HANDLE:
HANDLE th = (HANDLE)_beginthreadex( ... ):
Після отримання дескриптора, якщо він у цій функції більше не потрібний, його закривають за допомогою CloseHandle() аналогічно до дескриптора процесу:
CloseHandle(th);
Розглянемо приклад задання функції потоку. Додаткові дані, які передаються під час виклику _beginthreadex() за допомогою параметра argument, доступні в цій функції через параметр типу void *.
unsigned int WINAPI thread_fun (void *num) {
printf ("потік %d почав виконання\n", (int)num);
//код функції потоку
printf ("потік %d завершив виконання\п". (int)num);
}
Ось приклад виклику _beginthreadex() з усіма параметрами:
unsigned tid;
int number = 0;
HANDLE th = (HANDLE) _beginthreadex (
NULL, 0. thread_fun, (void *)++number, 0. &tid):
Після створення потоку може виникнути потреба змінити його характеристики. Якщо це необхідно зробити у функції потоку, варто знати, як отримати доступ до його дескриптора. Для цього використовують функцію GetCurrentThread():
unsigned int WINAPI thread_fun (void *num) { HANDLE curth = GetCurrentThread():
}
Завершення потоків у Win32 АРІ
Функцію потоку можна завершити двома способами.
1. Виконати у ній звичайний оператор return (цей спосіб є найнадійнішим):
unsigned WINAPI thread_fun (void *num) {
return 0:
}
2. Викликати функцію _endthreadex() з параметром, що дорівнює коду повернення:
unsigned WINAPI thread_fun (void *num) { _endthreadex(0);
}
Приєднання потоків у Win32 АРІ
Приєднання потоків у Win32 АРІ, подібно до очікування завершення процесів, здійснюється за допомогою функції WaitForSingleObject(). Базовий синтаксис її використання з потоками такий:
HANDLE th = (HANDLE) _beginthreadex (...);
if (WaitForSingleObject(th. INFINITE) !- WAIT_FAILED) { // потік завершений успішно
} CloseHandle(th);
Завдання
1. Застосовуючи інтерфейс потоків Win32, розробити додаток для Windows XP, що реалізує паралельне виконання коду двома потоками. Основний потік додатку Т створює потік t. Далі кожен із потоків виконує цикл (наприклад, до 30). На кожній ітерації циклу він збільшує значення локального лічильника на одиницю, відображає це значення з нового рядка і призупиняється на деякий час (потік Т - на час Т, потік t - t). Після завершення циклу потік Т приєднує t.
2. Відповісти на наступні запитання:
* Як залежать результати виконання цього застосування від значень Т і t?
* Як зміняться ці результати, якщо потік t не буде приєднано?
Звіт повинен містити:
постановку задачи; блок-схеми алгоритмів у відповідності з ГОСТ 19.002-80 і ГОСТ 19.003-80; лістінг програми з коментарями; результат виконання програми.
Список рекомендованих джерел
1. Шеховцов В.А. Операційні системи. - К.: Видавнича група BHV, 2005. - 576 с.: іл.
2. Рихтер Д. Windows для профессионалов: Создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows. - М.: Русская редакция, 2001. - 752с.
3. Харт. Дж.В. Системное программирование в среде Win32. - М.: Вильямс, 2001. - 46 4 с.
4. Рихтер Джеффри. Windows для профессионалов: Программирование для Windows 95 и Windows NT 4.0. на базе Win32/API. - М.: Изд. отдел "Русская редакция",1997. - 712 с.
5. Румянцев П.В. Азбука программирования в Win32 API. - М.: Радио и связь,1998. -272 с.
Документ
Категория
Рефераты
Просмотров
50
Размер файла
68 Кб
Теги
робота, практична
1/--страниц
Пожаловаться на содержимое документа