Процеси, нитки і волокна в ос windows
1. Процеси, нитки і волокна в ОСWindows
Процесом зазвичай називають екземпляр виконуваної програми. Хоча на перший погляд здається, що програма і процес поняття практично однакові, вони фундаментально відрізняються один від одного. Програма представляє собою статичний набір команд, а процес це набір ресурсів і даних, що використовуються при виконанні програми. Процес в Windows складається з наступних компонентів:
- структура даних, що містить всю інформацію про процес, в тому числі список відкритих дескрипторів різних системних ресурсів, унікальний ідентифікатор процесу, різну статистичну інформацію і т.д .;
- унікальний ідентифікатор нитки;
- вміст набору регістрів процесора, що відображають стан процесора;
- два стека, один з яких використовується ниткою при виконанні в режимі ядра, а інший - в режимі користувача;
- закриту область пам'яті, звану локальною пам'яттю нитки (thread local storage, TLS) і використовувану підсистемами, run-time бібліотеками і DLL.
Щоб всі нитки працювали, операційна система відводить кожній з них певний процесорний час. Тим самим створюється ілюзія одночасного виконання ниток (зрозуміло, для багатопроцесорних комп'ютерів можливий істинний паралелізм). У Windows реалізована система витісняє планування на основі пріоритетів, в якій завжди виконується нитка з найбільшим пріоритетом, готова до виконання. Обрана для виконання нитка працює протягом деякого періоду, званого квантом. Квант визначає, скільки часу буде виконуватися нитку, поки операційна система не перерве її. Після закінчення кванта операційна система перевіряє, чи готова до виконання інша нитка з таким же (або великим) рівнем пріоритету. Якщо таких ниток не виявилося, поточної нитки виділяється ще один квант. Однак нитка може не повністю використовувати свій квант. Як тільки інша нитка з більш високим пріоритетом готова до виконання, поточна нитка витісняється, навіть якщо її квант ще не закінчився.
Всякий раз, коли виникає переривання від таймера, з кванта нитки віднімається 3, і так до тих пір, поки він не досягне нуля. Частота спрацьовування таймера залежить від апаратної платформи. Наприклад, для більшості однопроцесорних x86 систем він становить 10 мс, а на більшості багатопроцесорних x86 систем - 15 мс.
Планування в Windows здійснюється на рівні ниток, а не процесів. Це здається зрозумілим, так як самі процеси не виконуються, а лише надають ресурси і контекст для виконання ниток. Тому при плануванні ниток, система не звертає уваги на те, якому процесу вони належать. Наприклад, якщо процес А має 10 готових до виконання ниток, а процес Б - дві, і всі 12 ниток мають однаковий пріоритет, кожна з них отримає 1/12 процесорного часу.
У Windows існує 32 рівня пріоритету, від 0 до 31. Вони групуються так: 31-16 - рівні реального часу; 15-1 - динамічні рівні; 0 - системний рівень, зарезервований для процесу обнулення сторінок (zero-page thread).
Пріоритет кожної нитки (базовий пріоритет нитки) складається з пріоритету її процесу і відносного пріоритету самої нитки. Є сім відносних пріоритетів ниток:
Normal: такий же як і у процесу;
Above normal: +1 до пріоритету процесу;
Timecritical: встановлює базовий пріоритет потоку для Realtime класу в 31,
для інших класів - в 15;
Idle: встановлює базовий пріоритет потоку для Realtime класу в 16,
для інших класів - в 1.
Якщо операційна система виконується на машині, де встановлено більше одного процесора, то за замовчуванням, нитка виконується на будь-якому доступному процесорі. Однак в деяких випадках, набір процесорів, на яких нитка може працювати, може бути обмежений. Це явище називається прив'язкою до процесорів (processoraffinity). Можна змінити прив'язку до процесорів програмно, через Win32 # 8209; функції планування.
2. Створення процесів
- Відкривається файл образу (EXE), який буде виконуватися в процесі. Якщо виконуваний файл не є Win32 додатком, то шукається спосіб підтримки (support image) для запуску цієї програми. Наприклад, якщо виконується файл з расшіреніем.bat, запускається cmd.exe і т.п.
- Створюється об'єкт Win32 «процес».
- Створюється первинна нитка (стек, контекст і об'єкт «нитка»).
- Підсистема Win32 повідомляється про створення нового процесу і нитки.
- Починається виконання первинної нитки.
3. Завершення процесів
Процес завершується якщо:
- Вхідна функція первинної нитки повернула управління.
- Одна з ниток процесу викликала функцію ExitProcess.
- Нитка іншого процесу викликала функцію TerminateProcess.
Приклад: Програма створює процес «Калькулятор».
int main (int argc, char * argv [])
ZeroMemory (si, sizeof (si));
ZeroMemory (pi, sizeof (pi));
if (! CreateProcess (NULL, «c: \\ windows \\ calc.exe», NULL, NULL, FALSE,
0, NULL, NULL, si, pi))
// Close process and thread handles.
4. Створення ниток
5. Завершення ниток
Нитка завершується якщо
- Функція нитки повертає управління.
- Нитка самознищується, викликавши ExitThread.
- Інша нитка даного або стороннього процесу викликає TerminateThread.
- Завершується процес, що містить дану нитку.
6. Створення волокон
Волокно може бути створено за допомогою системного виклику CreateFiber з основної нитки процесу чи отримано шляхом перетворення поточної нитки за допомогою функції ConvertThreadToFiber. Перемикання між волокнами може бути організовано за допомогою функції SwitchToFiber. але її виклик можна здійснювати тільки з волокна.
Приклад: Програма створює 4 волокна, кожне з яких виконує перемикання на наступне волокно, якщо число перемикань більше 10, робота завершується.
#define _WIN32_WINNT 0x0400
void WINAPI Func (void *)
printf ( "Fiber Number% d \ n", Counter% 4);
SwitchToFiber (fiber [Counter% 4]);
int main (int argc, char * argv [])
fiber [0] = CreateFiber (0, Func, NULL);
fiber [1] = CreateFiber (0, Func, NULL);
fiber [2] = CreateFiber (0, Func, NULL);
fiber [3] = CreateFiber (0, Func, NULL);
// для перемикання на перше волокно необхідно перетворити поточну нитку в волокно
7. Знищення волокон
Для примусового знищення волокна застосовується функція DeleteFiber. Також для знищення волокна можуть бути використані всі функції, призначені для знищення ниток.
Для припинення виконання роботи нитки можна використовувати різні способи.
Функція Sleep () призупиняє роботу нитки на задане число мілісекунд. Якщо в якості аргументу ви вкажете 0 ms, то відбудеться наступне. Нитка відмовиться від свого кванта процесорного часу, однак тут же з'явиться в списку ниток, готових до виконання. Іншими словами відбудеться навмисне перемикання ниток (вірніше сказати, спроба перемикання - адже наступного для виконання ниткою цілком може стати та ж сама).
Приклад. Програма створює процес «Калькулятор» і через 15 секунд його знищує.
int main (int argc, char * argv [])
memset (StartUpInfo, 0, sizeof (STARTUPINFO));
If (CreateProcess (NULL, «c: \\ windows \\ calc.exe», NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS, NULL, NULL, StartUpInfo, ProcessInfo))
TerminateProcess (ProcessInfo.hProcess, 0);
Функція WaitForSingleObject () призупиняє виконання нитки до тих пір, поки не відбудеться одна з двох подій:
- закінчиться затримку читання;
- очікуваний об'єкт перейде в сигнальне (signaled) стан.
По поверненню значенням можна зрозуміти, яке з двох подій відбулося. Очікувати за допомогою wait # 8209; функцій можна більшість об'єктів ядра, наприклад, об'єкт «процес» або «нитка», щоб визначити, коли вони завершать свою роботу.
Функції WaitForMultipleObjects передається відразу масив об'єктів. Можна очікувати спрацьовування відразу всіх об'єктів або якогось одного з них.
Приклад. Програма створює дві однакових нитки і очікує їх завершення. Нитки просто виводять текстове повідомлення, яке передано їм при ініціалізації.
unsigned ThreadFunc (void * arg)
char ** str = (char **) arg;
MessageBox (0, str [0], str [1], 0);
int main (int argc, char * argv [])
char * InitStr1 [2] =; // рядок для першої нитки
char * InitStr2 [2] =; // рядок для другої нитки
unsigned long uThreadIDs [2];
hThreads [0] = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc,
hThreads [1] = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc,
// Чекаємо, поки нитки не завершать свою роботу
WaitForMultipleObjects (2, hThreads, TRUE, INFINITE);
У рефераті розглянуті різні WIN API функції і послідовність дій для створення та роботи з процесами, нитками і фолокнамі при створенні вміндоуз-додатків, їх застосування та особливості. Для отримання повної інформації про призначення, використання і синтаксисі всіх функцій WIN32 API необхідно скористатися системою допомоги MSSDK, що входить до складу середовищ програмування BorlandDelphi або CBuilder, а також MSDN, що поставляється в складі системи програмування VisualC.