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

4.3. Проблеми взаємодії процесів

4.3.1. Ізоляція процесів та їх взаємодія

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

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

По-друге, проектування і налагодження програм надзвичайно ускладнилися б, якби програміст повинен був враховувати непередбачуване вплив інших процесів.

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

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

Поняття взаємодії процесів включає в себе кілька видів взаємодії, основними з яких є:

· Синхронізація процесів, тобто, спрощено кажучи, очікування одним процесом небудь подій, пов'язаних з роботою інших процесів;

· Обмін даними між процесами.

Набір засобів, призначених для взаємодії процесів, часто позначають абревіатурою IPC (InterProcess Communication). Склад функцій і методів обумовлений багаторічним досвідом як програмістів-практиків, так і теоретиків, що розглядають проблеми взаємодії паралельних процесів.

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

4.3.2. Проблема взаємного виключення процесів

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

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

Процес A: Процес B:

Процесс A:

Процесс B:

. . .

R1 := N;

R1 := R1 - 1;

N := R1;

. . .

. . .

R2 := N;

R2 := R2 + 1;

N := R2;

. . .

Уявімо собі тепер, що при квазіпараллельний реалізації процесів в ході виконання цих трьох операторів відбувається перемикання процесів. В результаті, в залежності від непередбачуваних випадковостей, порядок виконання операторів може виявитися різним, наприклад:

1) R1: = N; R2: = N; R2: = R2 + 1; N: = R2; R1: = R1 - 1; N: = R1;

2) R2: = N; R2: = R2 + 1; R1: = N; R1: = R1 - 1; N: = R1; N: = R2;

3) R1: = N; R1: = R1 - 1; N: = R1; R2: = N; R2: = R2 + 1; N: = R2;

Ну і що? А те, що у випадку 1 значення N в результаті виявиться зменшеним на 1, у випадку 2 - збільшеним на 1, і тільки в разі 3 значення N, як і належить, не зміниться.

Можна навести менш екзотичні приклади.

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

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

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

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

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

Задовго до створення багатозадачних систем розробники засобів автоматики зіткнулися з неприємним ефектом залежності результату операції від випадкового і непередбачуваного співвідношення швидкостей поширення різних сигналів в електронних схемах. Цей ефект вони назвали «гонками». Ми тут ведемо мову, по суті, про те ж.

Для більш чіткого опису ситуації було введено поняття критичної секції.

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

У прикладі з квитками наведені три оператори в кожному з процесів складають критичну секцію цього процесу по відношенню до загальної змінної N.

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

А як їм це заборонити?

На перший погляд здається, що ця проблема (її називають проблемою взаємного виключення процесів) вирішується просто. Наприклад, можна ввести булеву змінну Free, доступну обом процесам і має сенс «критична область вільна». Кожен процес перед входом в свою критичну область повинен чекати, поки ця змінна не стане істинною, як показано нижче:

Процесс A:

Процесс B:

. . .

while not Free do

;

Free := false;

(критическая секция A)

Free := true;

. . .

. . .

while not Free do

;

Free := false;

(критическая секция B)

Free := true;

. . .

В обох процесах цикл while не робить нічого, крім очікування, поки інший процес вийде зі своєї критичної секції.

А чи не потрібно було щось зробити зі змінною Free ще до запуску процесів A і B?

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

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

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

· У будь-який момент часу не більше, ніж один процес може знаходитися в критичній секції;

· Якщо критична секція вільна, то процес може безперешкодно увійти в неї;

· Всі процеси рівноправні.

Спробуйте самі знайти таке рішення. У книгах / 3 / і / 4 / можна знайти кілька варіантів рішення з аналізом їхніх помилок.

Зрештою правильні алгоритми вирішена завдання взаємного виключення запропонували спочатку Деккер (його алгоритм досить заплутаний, що часто трапляється з першими рішеннями складних завдань), потім Пітерсон, чий алгоритм простіше і зрозуміліше.

Для допитливих приводимо рішення Пітерсона. У ньому використовуються булеві змінні flagA, flagB, спочатку рівні false, і змінна перераховується типу turn: A.. B.

Процесс A:

Процесс B:

. . .

flagA := true;

turn := B;

while flagB and turn = B do

;

(критическая секция A)

flagA := false;

. . .

. . .

flagB := true;

turn := A;

while flagA and turn = A do

;

(критическая секция B)

flagB := false;

. . .

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]