Особливості багатозадачності в середовищі Windows

38477
знаков
1
таблица
1
изображение

Контрольна робота

з інформатики

Особливості багатозадачності в середовищі Windows


Вступ

Основні поняття багатозадачності в Windows 95 - процес (задача) і потік (нитка). Під процесом розуміється виконання програми в цілому (WinWord, Excel, Visual C++ і т.д.) Потоками у свою чергу є частини процесу, що виконуються паралельно.

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

Хоча на перший погляд здається, що програма і процес поняття практично однакові, вони фундаментально відрізняються один від одного. Програма представляє собою статичний набір команд, а процес це набір ресурсів і даних, що використовуються при виконанні програми. Процес в Windows складається з наступних компонентів:

- Структура даних, що включає в себе всю інформацію про процес, в тому числі список відкритих дескрипторів різних системних ресурсів, унікальний ідентифікатор процесу, різноманітну статистичну інформацію і т.д.;

- Адресний простір - діапазон адресів віртуальної пам‘яті, яким може користуватися процес;

- Програма, що виконується і дані, що проектуються на віртуальний адресний простір процесу.

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

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

Приклад: один потік підготовляє дані, інший їх сортує, а третій виводить результат у файл. Передавши готові дані другому потоку на сортування, перший починає обробку нового блоку. Тим часом другий потік повідомляє третьому, що можна виводити результати. Роботу цих трьох потоків необхідно синхронізувати.

Всі потоки в системі повинні мати доступ до системних ресурсів — кучам, послідовним портам, файлам, вікнам і т д. Якщо один із потоків запросить монопольний доступ до якого-небудь ресурсу, іншим потокам, яким теж потрібен цей ресурс, не вдасться виконати свої задачі. А с другої сторони, просто недопустимо, щоб потоки безконтрольно користувались ресурсами. Інакше може статися так, що один потік пише в блок пам‘яті, з якого інший щось зчитує.

Потоки повинні взаємодіяти один з одним в двох основних випадках:

1) спільно використовуючи один і той же ресурс (щоб не розрушити його);

2) коли треба повідомити інші потоки про завершення яких-небудь операцій

В Windows є маса засобів, що спрощують синхронізацію потоків. Але точно спрогнозувати, в який момент потоки будуть робити то-то и то-то, надзвичайно складно.


Механізми синхронізації

Найбільш простим механізмом синхронізації є використання Interlocked-функцій. Використання цих функцій гарантує “атомарне” виконання потрібних операцій, тобто потоки не будуть заважати один одному.

Пояснимо на прикладі:

// definition of global viriable lorig g_x = 0;

DWORD WINAPI ThreadFunc1(PVOID pvParam) {

g_x++;

return(0); }

DWORD WINAPI ThreadFunc2(PVOID pvParam} {

g_x++;

return(0); }

Нема ні якої впевненості, що отримаємо двійку, тому що ми не управляємо механізмом витіснення потоків.

// definition of global viriable long g_x = 0;

DWORD WINAPI ThreadFunc1(PVOID pvParam) {

InterlockedExchangeAdd(&g_x, 1);

return(0); }

DWORD WINAPI ThreadFunc2(PVOID pvPararr) {

InterlockedExchangeAdd(&g_x, 1);

return(0); }

Тут вже можна бути впевненим, що значення g_x=2.

Розглянемо ці функції більш детально

Якщо кілька потоків мають доступ до однієї змінного, те немає ніякої гарантії, що в процесі зміни значення цієї змінний одним потоком не відбудеться переключення на інший потік, що може читати її значення. Інший потік у цьому випадку одержить невірну інформацію. Для запобігання таких конфліктів у Windows 95 уведений ряд функцій, що дозволяють коректно змінювати змінні, доступ до яких мають кілька потоків. Перелічимо функції, що охороняють від переключення під час зміни значення змінної:

LONG InterlockedIncrement (LPLONG lpAddend) - збільшує значення за адресою lpAddend на одиницю;

LONG InterlockedDecrement (LPLONG lpAddend) - зменшує значення за адресою lpAddend на одиницю;

LONG InterlockedExchange (LPLONG Target, LONG Value) - заміняє значення, що знаходиться за адресою Target, на значення, передане в параметрі Value;

LONG InterlockedExchangeAdd (PLONG Addend, LONG Increment) - додає до значення за адресою Addend значення Increment;

PVOID InterlockedCompareExchange (PVOID *Destination, PVOID Exchange, PVOID Comperand) - порівнює значення за адресою Destination зі значенням, переданим у параметрі Comperand, і якщо ці значення рівні, то за адресою Destination міститься значення, передане в параметрі Exchange.

Іншими словами, якщо в тексті програми є загальна змінна, те її зміна повинна вироблятися в такий спосіб:

{ long Val;

....

Val++; // неправильно

InterlockedIncrement(&Val); // правильно

...

}


Усі спроби зробити щось, що вимагає моментальної реакції на зовнішні події, у середовищі Windows 3.x приводили до більш ніж скромних результатів, тому що подібні програми здобували відносно стандартизований, але неповороткий графічний інтерфейс, і більше нічого. Windows 95 у принципі дозволяє розробляти критичне вчасно реакції ПО типу систем керування.

Цей метод хороший для дуже простих речей, для більш складної синхронізації він не допоможе. На щастя у Windows передбачено п'ять стандартних механізмів для синхронізації процесів і потоків:

семафор

критична секція

м’ютекс

подія

таймер

Розглянемо кожний з цих механізмів.

Критична секція

80.gif (4833 b)

Критична секція - це частина коду, доступ до якого тепер має тільки один потік. Інший потік може звернутися до критичного розділу, тільки коли перший вийде з нього.

Для роботи з критичними секціями використовуються наступні функції:

VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) - ініціалізація синхронізатора типу критичний розділ.

lpCriticalSection - покажчик на змінну типу CRITICAL_SECTION.

VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) - запит на вхід у критичну секцію(розділ)

lpCriticalSection - покажчик на змінну типу CRITICAL_SECTION.

VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) - вихід із критичного розділу (звільнення семафора).

lpCriticalSection - покажчик на змінну типу CRITICAL_SECTION.

VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) - видалення критичного розділу (звичайно при виході з програми).

lpCriticalSection - покажчик на змінну типу CRITICAL_SECTION.

Отже, для створення критичного розділу необхідно ініціалізувати структуру CRITICAL_SECTION. Що Windows у цій структурі зберігає, нас не стосується - важливо, що покажчик на цю структуру ідентифікує наш семафор.

Створивши об'єкт CRITICAL_SECTION, ми можемо працювати з ним, тобто можемо позначити код, доступ до якого для одночасно виконуються задач потрібно синхронізувати.

Розглянемо такий приклад. Ми хочемо записувати і зчитувати значення з деякого глобального масиву mas. Причому запис і зчитування повинні вироблятися двома різними потоками. Цілком природно, що краще якщо ці дії не будуть виконуватися одночасно. Тому введемо обмеження на доступ до масиву.

І хоча приведений нами приклад подібного обмеження (см. лістинг 1)надзвичайно спрощений, він добре ілюструє роботу синхронізатора типу критичний розділ: поки один потік "володіє" масивом, інший доступу до нього не має.


М‘ютекси (взаємовиключення)

М’ютекс (взаємовиключення, mutex) - це об’єкт синхронізації, який установлюється в особливий сигнальний стан, коли не зайнятий яким-небудь потоком. Тільки один потік володіє цим об’єктом в любий момент часу, звідси и назва таких об‘єктів – одночасний доступ до спільного ресурсу виключається. Наприклад, щоб виключити запис двох потоків в спільний участок пам’яті в один і то й же час, кожний потік очікує, коли звільниться м’ютекс, стає його власником и тільки потім пише щось в цю ділянку пам’яті. Після всіх необхідних дій м’ютекс звільняється, надаючи іншим потокам доступ до спільного ресурсу.

Два (або більше) процесів можуть створити м‘ютекс з одним і тим же іменем, визвавши метод CreateMutex. Перший процес дійсно створює м’ютекс, а наступні процеси отримують хендл існуючого вже об‘єкта. Це дає можливість декільком процесам отримати хендл одного і того ж м’ютекса, звільняючи програміста від необхідності турбуватися про те, хто насправді створює м’ютекс. Якщо використовується такий підхід, бажано встановити флаг bInitialOwner в FALSE, інакше виникнуть певні труднощі при визначенні справжнього “творця” м’ютекса.

Декілька процесів можуть отримати хендл (handle) одного й того ж м‘ютекса, що робить можливим взаємодію між процесами. Ви можете використовувати наступні механізми такого підходу:

Дочірній процес, створений за допомогою функції CreateProcess може наслідувати хендл м‘ютекса у випадку, якщо при його (м‘ютекса) створенні функцією CreateMutex був вказаний параметр lpMutexAttributes.

Процес може отримати дублікат існуючого м‘ютекса з допомогою функції DuplicateHandle.

Процес може вказати ім‘я існуючого м‘ютекса при виклику функцій OpenMutex або CreateMutex.


#include <windows.h>

#include <process.h>

#include <stdio.h>

HANDLE hMutex;

int a[ 5 ];

void Thread(void* pParams)

{

int i, num = 0;

while (TRUE)

{

WaitForSingleObject(hMutex, INFINITE);

for (i = 0; i < 5; i++) a[ i ] = num;

ReleaseMutex(hMutex);

num++;

}

}

int main(void)

{

hMutex = CreateMutex(NULL, FALSE, NULL);

_beginthread(Thread, 0, NULL);

while(TRUE)

{

WaitForSingleObject(hMutex, INFINITE);

printf("%d %d %d %d %d\n",

a[ 0 ], a[ 1 ], a[ 2 ],

a[ 3 ], a[ 4 ]);

ReleaseMutex(hMutex);

}

return 0;

}


Як видно з результату роботи процесу, основний потік (сама програма) і потік hMutex дійсно працюють паралельно (червоним кольором позначений стан, коли основний потік виводить масив під час його заповнення потоком hMutex):

81751652 81751652 81751651 81751651 81751651

81751652 81751652 81751651 81751651 81751651

83348630 83348630 83348630 83348629 83348629

83348630 83348630 83348630 83348629 83348629

83348630 83348630 83348630 83348629 83348629

Приклад. Допустимо, в програмі використовується ресурс, наприклад, файл або буфер в пам‘яті. Функція WriteToBuffer() викликається з різних потоків. Щоб уникнути колізій при одночасному зверненні до буферу з різних потоків, використовуємо м‘ютекс. Перед тим як звернутися до буфера, очікуємо „звільнення” м‘ютекса.

HANDLE hMutex;

int main()

{

hMutex = CreateMutex(NULL, FALSE, NULL); // Создаем мьютекс в свободном состоянии

//...

// Создание потоков, и т.д.

//...

}

BOOL WriteToBuffer()

{ DWORD dwWaitResult;

// Ждем освобождения мьютекса перед тем как обратиться к буферу.

dwWaitResult = WaitForSingleObject(hMutex, 5000L); // 5 секунд на таймаут

if (dwWaitResult == WAIT_TIMEOUT) // Таймаут. Мьютекс за єто время не освободился.

{

return FALSE;

}

else // Мьютекс освободился, и наш поток его занял. Можно работать.

{

Write_to_the_buffer().

...

ReleaseMutex(hMutex); // Освобождаем мьютекс.

}

return TRUE;

Семафор

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

Semaphore – глобальний об’єкт синхронізації, що має лічильник для ресурсів, з ним пов‘язаних. В достатньо грубому приближенні м‘ютекс можна розглядати, як частковий випадок семафора з двома станами.

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

Розглянемо основні функції семафора, що виключає, на прикладі роботи з об'єктами mutex.

1. Створення об'єкта mutex

HANDLE CreateMutex(

LPSECURITY_ATTRIBUTES lpMutexAttributes,

BOOL bInitialOwner,

LPCTSTR lpName)

lpMutexAttributes - покажчик на структуру SECURITY_ATTRIBUTES (у Windows 95 даний параметр ігнорується);

bInitialOwner - указує первісний стан створеного об'єкта (TRUE - об'єкт відразу стає зайнятим, FALSE - об'єкт вільний);

lpName - указує на рядок, що містить ім'я об'єкта. Ім'я необхідне для доступу до об'єкта інших процесів, у цьому випадку об'єкт стає глобальним і їм можуть оперувати різні програми. Якщо вам не потрібний іменований об'єкт, то вкажіть NULL. Функція повертає покажчик на об'єкт mutex. Надалі цей покажчик використовується для керування семафором, що виключає.


Информация о работе «Особливості багатозадачності в середовищі Windows»
Раздел: Информатика, программирование
Количество знаков с пробелами: 38477
Количество таблиц: 1
Количество изображений: 1

Похожие работы

Скачать
19688
0
0

... широка рекламна кампанія, всі виробники ПЗ почали переробляти свої продукти для цієї нової ОС, виробники комп’ютерів і комплектуючих намагались отримати логотип Designed for Windows 95. Причина, по якій Windows 95 опинилася в центрі загальної уваги, проста: це було саме важливе оновлення системи Windows з часів появи в 1990 році Windows 3.0. Користувачі тепер отримували переваги об’єктно – оріє ...

Скачать
259712
25
12

... та знизу ( нижній колонтитул ) у межах одного розділу або всього документа. Правильний вибір цієї інформації дає змогу читачеві краще орієнтуватися в документі. 5.4 Уведення інформації   Інформаційна система маркетингу – це сукупність інформації, апаратно-програмних і технологічних засобів, засобів телекомунікацій, баз і банків даних, методів і процедур, персоналу управління, які реалізують ...

Скачать
36821
0
1

... і додатки, такі як Mіcrosoft SQL Server і Exchange Server, також включають компоненти, що працюють як служби NT. ·     Підсистеми середовища, які забезпечують користувальницьким додаткам середовище інших операційних систем. Wіndows NT поставляється із трьома підсистемами: Wіn32, Posіx і OS/2 2.1. ·     Користувальницькі додатки одного з п'яти типів: Wіn32, Wіndows 3.1, MS-DOS, Posіx або OS/2 ...

Скачать
94287
22
5

... . Розділ “Керівництво користувача” призначений для вивчення , використання і засвоєння пакету програм по вирішенню задачі “Облік наявності та руху кадрiв”. Далі цей пакет програм буде називатися ПП “Кадр”. У розділі наведені основні відомості для роботи у середовищі автоматизованої системи, поданий опис режимів і функцій ПП, порядку дій користувача. Сукупність програмних засобів забезпечує ...

0 комментариев


Наверх