Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
metod_lab_ps_2_SPO_ch2_lab_rab (1).doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
341.5 Кб
Скачать

3.3 Самостійна підготовка

  • Підготуйте бланк звіту. Проробіть рекомендовану літературу [1],[2].

  • При підготовці зверніть увагу на такі питання:

а) необхідність монопольного користування спільними даними в мнопоточній програмі;

б) основи спін-блокування, переваги та недоліки;

в) interlocked-функції API Win32;

г) поняття і організація критичних секцій;

д) правила використання функцій роботи з критичними секціями.

  • Уважно проаналізуйте текст програми synchr1.asm (додаток С), у якій два потоки реалізують запис даних в один файл на жорсткому диску в асинхронному режимі. Ділянки коду, що відповідають запису даних, оформлені як критична секція в обох потоках. Для контролю монопольного доступу кожного потоку до файлу використовуються функції роботи з критичними секціями.

3.4 Порядок виконання роботи

  • В будь якому текстовому редакторі наберіть текст модуля synchr1.asm, який наведено у додатку С і збережіть його на диску.

  • Сформуйте модуль, що виконується (файл synchr1.exe).

  • Перевірте роботу програми synchr1.exe.

  • Дослідіть як зміниться результат запису у файл, якщо закоментувати рядки коду, пов’язані з викликом функцій EnterCriticalSection, LeaveCriticalSection. Зробіть у звіті відповідні висновки.

  • Модифікуйте програму з використанням замість спеціалізованих функцій роботи с критичною секцією функції InterlockedExchange.

  • Підготуйте модифіковану Вами програму до виконання за допомогою засобів пакету TASM.

  • Протестуйте роботу Вашої програми і занесіть у звіт її текст.

4 Синхронізація потоків у режимі ядра

4.1 Мета роботи

  • Вивчення особливостей організації взаємодії між паралельними потоками за допомогою об’єктів ядра Win32.

  • Засвоєння функцій API, які призначені для синхронізації потоків і процесів з переводом у режим ядра.

  • Опанування навичками синхронізації потоків за допомогою об’єктів ядра.

4.2 Основні відомості

Хоча механізми синхронізації в користувальницькому режимі забезпечують високу бистродію, їм властива низка обмежень, і в деяких випадках вони просто не будуть працювати.

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

Об’єкти ядра “процес” та “потік” перебувають в зайнятому стані доки виконується відповідний процес або потік, та переходять у вільний стан коли процес або потік завершуються. Усередині цих об’єктів підтримується булєва змінна, яка при створенні об’єкта приймає значення FALSE (“зайнято”). По закінченні роботи відповідного процесу або потоку операційна система змінює значення цієї змінної на TRUE, що свідчить про те, що об’єкт є вільним.

У вільному та зайнятому стані можуть перебувати такі об’єкти ядра:

  • процеси,

  • потоки,

  • завдання,

  • файли,

  • консольне введення,

  • повідомлення про зміну файлів,

  • події,

  • очікувані таймери,

  • семафори,

  • м’ютекси.

У складі API Win32 є функції, які дозволяють потоку в любий момент зупинитися та очікувати доки визначений об’єкт ядра не перейде у вільний стан. З усього сімейства цих функцій частіше за всі використовується WaitForSingleObject.

Цій функції передаються два параметри.

  • Параметр hObject є 32-бітним дескриптором (описувачем) відповідного об’єкту ядра.

  • Параметр dwMilliseconds (типу DWORD) вказує скільки часу (у мілісекундах) потік готовий очікувати звільнення об’єкту. Значення INFINITE цього параметра (яке визначене як –1) свідчить про те, що потік готовий очікувати скільки завгодно.

Протягом очікування потоку не надається процесорний час, що економить ресурси системи. Значення, що повертається цією функцією характеризує об’єкт, дескриптор якого передається у якості аргументу. Докладніше про можливі значення можна узнати з довідкової інформації (див., наприклад, Platform SDK documentation на сайті компанії Microsoft).

Самим простим об’єктом ядра, який може використовуватись для синхронізації потоків, є подія. Ці об’єкти місять лічильник (як усі об’єкти ядра), та дві булєві змінні. Одна визначає тип даного об’єкту-події, друга – його стан (“зайнято” або “вільно”). Події просто повідомляють про закінчення деякої операції. Об’єкти – події бувають двох типів: зі скиданням вручну або з автоскиданням. Перші дозволяють після здійснення події виконуватися декільком потокам, другі – тільки одному. Ініціалізуючий потік переводить об’єкт – подію у стан “зайнято” і переходить до своєї операції. Після закінчення він переводить об’єкт – подію у вільний стан, що дає можливість другим потокам, що очікували переходу події у такий стан, прокинутись і знов стати такими, що плануються.

Об’єкт ядра “подія” створюється функцією CreateEvent.

Цієї функції передаються три параметри.

  • Параметр psa є покажчиком на структуру типу SECURITY_ATTRIBUTES. Якщо достатньо, щоб об’єкту ядра “подія” були присвоєні атрибути захисту за умовчанням (що буває частіше за всього), то в цьому параметрі передають значення NULL. А для того, щоб дочірні процеси змогли успадкувати описувач цього об’єкту, треба визначити структуру типу SECURITY_ATTRIBUTES та ініціалізувати її елемент hinheritHandle значенням TRUE.

  • Параметр fManualReset (булєва змінна) повідомляє системі, чи буде об’єкт зі скиданням вручну (TRUE), або з автоскиданням (FALSE).

  • Параметр fInitialState визначає початковий стан події — вільний (TRUE), або зайнятий (FALSE).

  • Параметр pszName є покажчиком на рядок, що визначає ім’я об’єкту. Цей параметр потрібний для сумісного використання об’єкту різними процесами. Якщо таке використання не планується, цей параметр може бути заданий як NULL.

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

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

Для м’ютексів визначені такі правила:

  • якщо його ідентифікатор потоку дорівнює 0 (у самого потоку не може бути такого ідентифікатору), м’ютекс не захоплений жодним потоком і перебуває у вільному стані;

  • якщо його ідентифікатор потоку не дорівнює 0, м’ютекс захоплений одним з потоків і перебуває у зайнятому стані;

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

Для використання м’ютексу один з потоків повинен створити його за допомогою функції CreateMutex. Цієї функції передаються три параметра. Перший та останній з них ідентичні відповідним параметрам функції CreateEvent. Другий параметр fIniLialOwner визначає початковий стан м’ютекса. Якщо в ньому передається FALSE, то м’ютекс не належить жодному потоку і перебуває у вільному стані. Якщо значення параметру TRUE, ідентифікатор потоку м’ютекса, стає рівним ідентифікатору потоку, що викликає функцію CreateMutex, а лічильник рекурсії отримує значення 1. При цьому м’ютекс спочатку перебуває у зайнятому стані.

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

Більш докладне описання роботи з розглянутими та іншими об’єктами ядра, що використовуються для синхронізації потоків, є, наприклад, в [1].