Лекція 19. Процеси та потоки. Синхронізація
19.1. Процеси
Процес - програма, яка виконується в поточний момент. Стандарт ISO 9000:2000 визначає процес як сукупність взаємозв'язаних і взаємодіючих дій, що перетворюють вхідні дані в вихідні.
Комп'ютерна програма сама по собі - це лише пасивна послідовність інструкцій, в той час як процес - це безпосереднє виконання цих інструкцій.
Також, процесом називають поточну програму і всі її елементи: адресний простір, глобальні змінні, регістри, стек, відкриті файли і так далі.
Зазвичай, процес в обчислювальній системі представлений (також кажуть, «володіє») наступними ресурсами:
- типом виконуваного машинного коду, асоційованого з програмою;
- пам'яттю (зазвичай деякою областю віртуальної пам'яті), яка включає в себе:
o виконуваний код;
o вхідні і вихідні
дані процесу;
o стек викликів
(для відстеження активних підпрограм);
o купу для
зберігання проміжних результатів обчислень, що генеруються під час виконання;
- дескрипторами ресурсів операційної системи, виділеними для процесу, наприклад, файл
- файловими дескрипторами (в термінології ОС Unix) або «хендлом» (в термінології ОС Windows);
- атрибутами безпеки, такими як власник і набір повноважень процесу (допустимих операцій);
- станом процесора (контекстом), таким як:
o вміст регістрів;
o схема
перетворення віртуальних адрес в фізичні;
o і т.д.
Купа (Heap) в інформатиці та програмуванні - назва структури даних, за допомогою якої реалізована динамічна пам'ять програми.
Розмір купи - розмір пам'яті, виділеної операційною системою (ОС) для зберігання купи.
Контекст пов'язаних з поточною діяльністю вивантажується в пам'ять, коли виконується перемикання на інший процес.
Операційна система зберігає більшу частину інформації про процеси в таблиці процесів.
В операційних системах, що підтримують потоки виконання, потоки також володіють власними ресурсами. Зазвичай це тільки стан процесора, хоча потоки можуть використовувати і інші ресурси.
Для зниження ймовірності впливу процесів один на одного і ймовірності відмови системи (наприклад, взаємних блокувань або пробуксовки) операційна система забезпечує ізоляцію процесів і виділяє необхідні їм ресурси. Також операційна система надає механізми для взаємодії процесів безпечними і передбачуваними способами.
19.2. Потоки та багатопотоковість
Потік виконання (Thread) - найменша одиниця обробки, виконання якої може бути призначено ядром операційної системи. Реалізація потоків виконання і процесів в різних операційних системах відрізняється один від одного, але в більшості випадків потік виконання знаходиться всередині процесу. Кілька потоків виконання можуть існувати в рамках одного і того ж процесу і спільно використовувати ресурси, такі як пам'ять, тоді як процеси не поділяють цих ресурсів. Зокрема, потоки виконання поділяють інструкції процесу (його код) і його контекст (значення змінних, які вони мають в будь-який момент часу). Як аналогію потоки виконання процесу можна порівняти з роботою декількох кухарів. Всі вони готують одну страву, читають одну і ту ж кулінарну книгу з одним і тим же рецептом і дотримуються її вказівок, причому не обов'язково всі вони читають на одній і тій же сторінці.
Багатопотоковість, як широко поширена модель програмування і виконання коду, дозволяє декільком потокам виконуватися в рамках одного процесу. Ці потоки виконання спільно використовують ресурси процесу, але можуть працювати і самостійно. Багатопотокова модель програмування надає розробникам зручну абстракцію паралельного виконання. Однак, мабуть, найбільш цікаве застосування технології є в тому випадку, коли вона застосовується до одного процесу, що дозволяє його паралельне виконання на багатопроцесорної системі.
Ця перевага багатопотокової програми дозволяє їй працювати швидше на комп'ютерних системах, які мають кілька процесорів, процесор з декількома ядрами або на кластері машин - з-за того, що потоки виконання програм природним чином піддаються дійсно паралельному виконанню процесів.
Іншим використанням багатопотоковості, застосовуваним навіть для однопроцесорних систем, є можливість для застосування реагування на введення даних. У однопотокових програмах, якщо основний потік виконання заблокований виконанням тривалого завдання, весь додаток може виявитися в замороженому стані. Переміщаючи такі тривалі завдання в робочий потік, який виконується паралельно з основним потоком, стає можливим для додатків продовжувати реагувати на дії користувача під час виконання завдань у фоновому режимі.
Операційні системи планують виконання потоків одним з двох способів:
- Пріоритетна багатопотоковість, взагалі кажучи, вважається більш досконалим підходом, так як вона дозволяє операційній системі визначити, коли має відбуватися перемикання контексту. Недолік пріоритетної багатопотоковості полягає в тому, що система може зробити перемикання контексту в невідповідний час, що призводить до інверсії пріоритету та інших негативних ефектів, яких можна уникнути, застосовуючи кооперативну багатопотоковість.
- Кооперативна багатопотоковість покладається на самі потоки і відмовляється від управління, якщо потоки виконання знаходяться в точках зупинки. Це може створити проблеми, якщо потік виконання очікує ресурс, поки він не стане доступним.
До кінця 1990-х процесори в настільних комп'ютерах не мали підтримки багатопотоковості, так як перемикання між потоками, як правило, відбувалося швидше, ніж повне перемикання контексту процесу. Процесори у вбудованих системах, які мають більш високі вимоги до поведінки в реальному часі, можуть підтримувати багатопотоковість за рахунок зменшення часу на перемикання між потоками, можливо, шляхом розподілу виділених реєстрових файлів для кожного потоку виконання, замість збереження/відновлення загального реєстрового файлу. В кінці 1990-х ідея виконання інструкцій декількох потоків одночасно, відома як одночасна багатопотоковість, під назвою Hyper-Threading, досягла настільних комп'ютерів з процесором Intel Pentium 4. Потім вона була виключена з процесорів архітектури Intel Core і Core 2, але пізніше відновлена в архітектурі Core i7.
19.3. Синхронізація процесів
Синхронізація процесів - це механізм, що дозволяє забезпечити цілісність будь-якого ресурсу (файл, дані в пам'яті), коли він використовується декількома процесами або потоками у випадковому порядку. Для синхронізації процесів і потоків використовуються семафори, м'ютекси і критичні секції. Альтернативою синхронізації може служити модель акторів або транзакційна пам'ять.
Семафор - об'єкт, що обмежує кількість потоків, які можуть увійти в задану ділянку коду.
М'ютекс (mutual exclusion - «взаємне виключення») - аналог одномісного семафора, що слугує в програмуванні для синхронізації одночасно виконуваних потоків. М'ютекс відрізняється від семафора тим, що тільки володіючий ним потік може його звільнити, тобто перевести в зазначений стан.
Критична секція - ділянка виконуваного коду програми, в якому проводиться доступ до загального ресурсу (даним або пристрою), який не повинен бути одночасно використаний більш ніж одним потоком виконання. При знаходженні в критичній секції двох (або більше) процесів виникає стан «гонки» («змагання»).
Для уникнення даної ситуації необхідне виконання чотирьох умов:
- Два процесу не повинні одночасно перебувати в критичних областях.
- У програмі не повинно бути припущень про швидкість або кількість процесорів.
- Процес, що знаходиться поза критичною областю, не може блокувати інші процеси.