Механізми Взаємодія між процесами в операційній
системі Unix h2>
Сергій Кузнецов p>
виникли проблеми h2>
Надмірна
набір системних засобів, призначених для забезпечення можливості
взаємодії та синхронізації процесів, які не обов'язково пов'язані
ставленням спорідненості p>
IPC
- Inter-Process Communication Facilities p>
з
появою UNIX System V Release 4.0 всі ці кошти були узаконені і увійшли до
фактичний стандарт ОС UNIX сучасного зразка p>
в
різних варіантах системи кошти IPC реалізуються по-різному p>
ефективність
реалізації розрізняється p>
ускладнюється
розробка мобільних асинхронних програмних комплексів p>
Пакет засобів IPC p>
UNIX System V Release 3.0 p>
кошти,
забезпечують можливість наявності загальної пам'яті між процесами (сегменти
розділяється пам'яті - shared memory segments) p>
кошти,
забезпечують можливість синхронізації процесів при доступі до спільно
використовуваних ресурсів, наприклад, до поділюваного пам'яті (семафори - semaphores) p>
кошти,
забезпечують можливість посилки процесом повідомлень іншому безпідставного
процесу (черги повідомлень - message queues) p>
Загальні
властивості всіх трьох механізмів: p>
для
кожного механізму підтримується загальносистемна таблиця, елементи якої
описують всіх існуючих в даний момент представників механізму
(конкретні сегменти, семафори або черги повідомлень) p>
елемент
таблиці містить деякий числовий ключ, який є вибраним
користувачем ім'ям представника відповідного механізму p>
процес,
бажаючий почати користуватися одним з механізмів, звертається до системи з
системним викликом із сімейства "get", у відповідь параметром є
числовий дескриптор p>
ключ IPC_PRIVATE p>
ключ IPC_CREAT p>
захист
доступу грунтується на тих же принципах, що і захист доступу до файлів p>
Колективна
пам'ять p>
shmget
створює новий сегмент розділяється пам'яті або знаходить існуючий сегмент з тим
ж ключем p>
shmat
підключає сегмент із зазначеним дескриптором до віртуальної пам'яті звертається
процесу p>
shmdt
відключає від віртуальної пам'яті раніше підключений до неї сегмент із зазначеним
віртуальним адресою початку p>
shmctl
служить для управління параметрами, пов'язаними з існуючим сегментом p>
Після
підключення сегмента розділяється пам'яті до віртуальної пам'яті процесу, він може
звертатися до відповідних елементів пам'яті з використанням звичайних машинних
команд читання і запису p>
shmid = shmget (key, size, flag); p>
size
визначає бажаний розмір сегмента в байтах p>
якщо
в таблиці розділяється пам'яті знаходиться елемент, що містить заданий ключ, і
права доступу не суперечать поточним характеристиками процесу, то значенням
системного виклику є дескриптор існуючого сегмента p>
реальний
розмір сегмента можна дізнатися за допомогою системного виклику shmctl p>
інакше
створюється новий сегмент з розміром не менше встановленого в системі
мінімального розміру сегмента розділяється пам'яті і не більше встановленого
максимального розміру p>
створення
сегмента не означає негайного виділення під нього основної пам'яті p>
відкладається
до виконання першого системного виклику підключення сегмента до віртуальної
пам'яті деякого процесу p>
при
виконання останнього системного виклику відключення сегмента від віртуальної
пам'яті відповідна основна пам'ять звільняється p>
virtaddr = shmat (id, addr, flags); p>
id
- Це раніше отриманий дескриптор сегмента p>
addr
- Бажаний процесом віртуальну адресу, який повинен відповідати початку
сегмента у віртуальній пам'яті p>
virtaddr
- Реальний віртуальний адреса початку сегмента p>
НЕ
обов'язково таке саме, як прямого параметра addr p>
якщо
addr == 0, ядро вибирає найбільш зручний віртуальну адресу початку сегмента p>
shmdt (addr);
p>
addr
- Віртуальний адреса початку сегменту у віртуальній пам'яті, раніше отриманий від
системного виклику shmat p>
shmctl (id,
cmd, shsstatbuf); p>
cmd
ідентифікує потрібне конкретна дія p>
важлива
функція знищення сегмента розділяється пам'яті p>
Семафори p>
Узагальнення
класичного механізму семафорів загального вигляду Діекстри p>
Доцільність
узагальнення сумнівна p>
Зазвичай
використовувався полегшений варіант двійкових семафорів p>
Відомий
алгоритм реалізації семафорів загального вигляду на основі двійкових p>
Семафор
в ОС UNIX: p>
значення
семафора p>
ідентифікатор
процесу, який хронологічно останнім працював з семафором p>
число
процесів, що очікують збільшення значення семафора p>
число
процесів, що очікують нульового значення семафора p>
Три
системних виклику: p>
semget
для створення і отримання доступу до набору семафорів p>
semop
для маніпулювання значеннями семафорів p>
semctl
для виконання керуючих операцій над набором семафорів p>
id = semget (key, count, flag); p>
key,
flag і id - звичайний сенс p>
count
- Число семафорів в наборі семафорів, що володіють одним і тим же ключем p>
індивідуальний
семафор ідентифікується дескриптором набору семафорів і номером семафора в
наборі p>
якщо
набір семафорів з вказаним ключем вже існує, то число семафорів у групі
можна дізнатися за допомогою системного виклику semctl p>
oldval = semop (id, oplist, count); p>
id
- Дескриптор групи семафорів p>
oplist
- Масив описувачів операцій над семафора групи p>
count
- Розмір цього масиву p>
повертається
значення останнього обробленого семафора p>
Елемент
масиву oplist: p>
номер
семафора у вказаному наборі семафорів p>
операція
p>
прапори
p>
Якщо
перевірка прав доступу проходить нормально p>
зазначені
в масиві oplist номера семафорів не виходять за межі загального розміру набору
семафорів p>
для
кожного елемента масиву oplist значення семафора змінюється відповідно до
значенням поля "операція" p>
Значення
поля операції позитивно p>
значення
семафора збільшується на одиницю p>
все
процеси, які очікують збільшення значення семафора, активізуються (пробуджуються)
p>
Значення
поля операції дорівнює нулю p>
якщо
значення семафора дорівнює нулю, вибирається наступний елемент масиву oplist p>
інакше
число процесів, що очікують нульового значення семафора, збільшується на одиницю
p>
звернувся
процес переводиться в стан очікування (присипляються) p>
Значення
поля операції негативно p>
(1)
його абсолютне значення менше або дорівнює значенню семафора p>
це
від'ємне значення додається до значення семафора p>
якщо
значення семафора стало нульовим, то ядро активізує всі процеси, які очікують
нульового значення цього семафора p>
(2)
значення семафора менше абсолютної величини поля операції p>
число
процесів, що очікують збільшення значення семафора збільшується на одиницю p>
поточний
процес відкладається p>
Прагнення
домогтися можливості уникати безвихідних ситуацій p>
Системний
виклик semop виконується як атомарна операція p>
Прапор
IPC_NOWAIT змушує ядро ОС UNIX не блокувати поточний процес p>
лише
повідомляти у відповідних параметрах про виникнення ситуації, що призвела б до
блокування процесу p>
semctl (id, number, cmd, arg); p>
id
- Це дескриптор групи семафорів p>
number
- Номер семафора в групі p>
cmd
- Код операції p>
arg
- Покажчик на структуру, вміст якої інтерпретується в залежності від
операції p>
Можна
знищити індивідуальний семафор у зазначеній групі p>
Черги
повідомлень p>
Чотири
системних виклику: p>
msgget
для утворення нової черги повідомлень або отримання дескриптора існуючої
черги p>
msgsnd
для посилки повідомлення (його постановки в чергу повідомлень) p>
msgrcv
для прийому повідомлення (вибірки повідомлення з черги) p>
msgctl
для виконання керуючих дій p>
msgqid
= Msgget (key, flag); p>
Повідомлення
зберігаються у вигляді зв'язного списку p>
Декскріптор
черги повідомлень - індекс у масиві заголовків черг повідомлень p>
В
заголовку черги зберігаються: p>
покажчики
на перше і останнє повідомлення в цій черзі p>
число
повідомлень p>
загальний
розмір в байтах повідомлень, що знаходяться в черзі p>
ідентифікатори
процесів, які останніми послали або прийняли повідомлення через дану
чергу p>
тимчасові
мітки останніх виконаних операцій msgsnd, msgrsv і msgctl p>
Структури
даних, що використовуються для організації черг повідомлень p>
p>
msgsnd (msgqid, msg, count, flag); p>
msg
- Це покажчик на структуру, яка містить цілочисельний тип повідомлення і
символьний масив p>
count
- Задає розмір повідомлення в байтах p>
flag
визначає дії ядра при виході за межі допустимих розмірів внутрішньої
буферної пам'яті p>
Умови
успішної постановки повідомлення в чергу: p>
процес
повинен мати право на запис у чергу p>
довжина
повідомлення не повинна перевищувати верхню межу p>
загальна
довжина повідомлень не повинна перевищувати встановленої межі p>
тип
повідомлення повинен бути позитивним цілим числом p>
Процес
продовжує своє виконання p>
Ядро
активізує (будить) всі процеси, які очікують надходження повідомлень з
черги p>
перевищується
верхня межа сумарної довжини повідомлень p>
звернувся
процес відкладається до розвантаження черги p>
але
є прапор IPC_NOWAIT (як для семафорів) p>
count = msgrcv (id, msg, maxcount,
type, flag); p>
msg
- Покажчик на структуру даних в адресному просторі користувача для
розміщення прийнятого повідомлення p>
maxcount
- Розмір області даних (масиву байтів) у структурі msg p>
type
специфікує тип повідомлення, яке бажано прийняти p>
flag
вказує ядра, що слід зробити, якщо у зазначеній черги повідомлень
немає повідомлення з вказаним типом p>
count
- Реальне число байтів, переданих користувачеві p>
Значенням
параметра type є нуль p>
вибирається
перше повідомлення p>
копіюється
в задану структуру для користувача даних p>
процеси,
відкладені через переповнення черги повідомлень, активізуються p>
якщо
значення параметра maxcount виявляється менше реального розміру повідомлення,
ядро не видаляє повідомлення з черги і повертає код помилки p>
якщо
задано прапор MSG_NOERROR, то вибірка повідомлення виробляється, і в буфер
користувача переписуються перший maxcount байтів повідомлення p>
Значення
type є позитивне ціле число p>
вибирається
перше повідомлення з таким же типом p>
Значення
type є негативне ціле число p>
вибирається
перше повідомлення, значення якого типу менше або рівне абсолютним значенням
type p>
В
черги відсутні повідомлення, відповідні специфікації type p>
процес
відкладається до появи в черзі необхідного повідомлення p>
але
є прапор IPC_NOWAIT p>
msgctl (id,
cmd, mstatbuf); p>
опитування
стану описувача черги повідомлень p>
зміна
його стану p>
знищення
черги повідомлень p>
Програмні
канали p>
Створення
неіменованного програмного каналу p>
pipe (fdptr);
p>
fdptr
- Це покажчик масиву з двох цілих чисел для розміщення дескриптора для
читання з програмного каналу (за допомогою read) та запису в програмний канал (з
допомогою write) p>
звичайні
дескриптори файлів p>
два
елемента таблиці відкритих файлів процесу p>
Створення
іменованих програмних каналів (або отримання доступу до існуючих) p>
Звичайний
системний виклик open p>
якщо
канал відкривається на запис, і ні один процес не відкрив його для читання, то
процес блокується до тих пір, поки деякий процес не відкриє цей канал
для читання p>
аналогічно
обробляється відкриття для читання p>
є
прапор NO_DELAY p>
Запис
і читання: read і write p>
при
запису дані містяться в початок каналу p>
при
читанні вибираються з кінця каналу p>
можливі
відкладання процесів p>
Закінчення
роботи процесу: close p>
при
виконання останнього закриття каналу за записом всі процеси, які очікують читання
з програмного каналу, активізуються з поверненням коду помилки з системної
дзвінка p>
Програмні
гнізда (sockets) p>
Підтримуваний
ядром механізм, що приховує особливості мережевої середовища і що дозволяє одноманітно
взаємодіяти процесів p>
що виконуються
на одному комп'ютері p>
в
межах однієї локальної мережі p>
рознесеним
на різні комп'ютери територіально розподіленої мережі p>
Перше
рішення: p>
UNIX
BSD 4.1 у 1982 р. p>
Три
складових: p>
компонент
рівня програмних гнізд (незалежний від мережевого протоколу і середовища передачі
даних) p>
компонентом
протокольного рівня (незалежний від середовища передачі даних) p>
компонентом
рівня управління мережним пристроєм p>
Одна
з можливих конфігурацій програмних гнізд p>
p>
Допустимі
комбінації протоколів і драйверів задаються при конфігурації системи p>
під
час роботи системи змінювати не можна p>
За
духу організація програмних гнізд близька до ідеї потоків p>
Але
менш гнучка схема p>
НЕ
допускає зміни конфігурації "на ходу" p>
Взаємодія
процесів засноване на моделі "клієнт-сервер" p>
процес-сервер
"слухає (listens)" своє програмне гніздо p>
процес-клієнт
намагається спілкуватися з процесом-сервером через інше програмне гніздо p>
ядро
підтримує внутрішні з'єднання і маршрутизацію даних від клієнта до сервера p>
Програмні
гнізда із загальними комунікаційними властивостями, такими як спосіб іменування та
протокольний формат адреси, групуються у домени p>
"домен
системи UNIX "для процесів, які взаємодіють через програмні
гнізда в межах одного комп'ютера p>
"домен
Internet "для процесів, які взаємодіють у мережі відповідно до
сімейством протоколів TCP/IP p>
Два
типу програмних гнізд p>
з
віртуальним з'єднанням (stream sockets) p>
дейтаграмним
гнізда (datagram sockets) p>
Віртуальні
з'єднання: p>
передача
даних від клієнта до сервера у вигляді безперервного потоку байтів з гарантією
доставки p>
до
початку передачі даних повинне бути встановлене з'єднання p>
дейтаграмним
програмні гнізда: p>
НЕ
гарантують абсолютної надійною, послідовною доставки повідомлень і
відсутності дублікатів дейтаграм p>
НЕ
потрібне попереднє встановлення з'єднань p>
За
замовчуванням забезпечується відповідний протокол для кожної допустимої комбінації
"домен-гніздо" p>
TCP
для віртуальних з'єднань p>
UDP
для дейтаграмним способу комунікацій p>
Створення
нового програмного гнізда: p>
sd
= Socket (domain, type, protocol); p>
domain
- Домен гнізда p>
type
- Тип (з віртуальним з'єднанням або дейтаграмним) p>
protocol
- Бажаний мережевий протокол p>
sd
- Дескриптор програмного гнізда p>
Закриття
(знищення) гнізда p>
close (sd)
p>
Зв'язування
раніше створеного програмного гнізда з ім'ям: p>
bind (sd,
socknm, socknlen); p>
sd
- Дескриптор раніше створеного програмного гнізда p>
socknm
- Адреса структури, яка містить ім'я (ідентифікатор) гнізда, відповідне
вимогам домену даного гнізда й використовуваного протоколу p>
для
домену системи UNIX ім'я є ім'ям об'єкту у файловій системі p>
при
створення програмного гнізда створюється файл p>
socknlen
- Довжина в байтах структури socknm p>
Запит
зв'язку з існуючим програмним гніздом з боку процесу-клієнта: p>
connect (sd,
socknm, socknlen); p>
сенс
параметрів, як у функції bind p>
ім'я
програмного гнізда на іншій стороні комунікаційного каналу p>
у
гнізда з дескриптором sd і у гнізда з ім'ям socknm повинні бути однакові
домен і протокол p>
якщо
тип гнізда з дескриптором sd - дейтаграмним, то connect служить для
системи інформування про адресу призначення пакетів, які в подальшому будуть
надсилатися за допомогою функції send p>
Інформування
про те, що процес-сервер планує встановлення віртуальних з'єднань через
вказане гніздо: p>
listen (sd,
qlength); p>
qlength
- Максимальна довжина черги запитів на встановлення з'єднання, які
повинні буферізованние системою, поки їх не вибере процес-сервер p>
Вибірка
процесом-сервером чергового запиту на встановлення з'єднання з зазначеним
програмним гніздом служить функція accept: p>
nsd = accept (sd, address, addrlen); p>
sd
- Дескриптор існуючого програмного гнізда, для якого раніше була
виконана функція listen p>
address
- Масив даних, до якого повинна бути поміщена інформація, що характеризує ім'я
програмного гнізда клієнта p>
addrlen
- Адреса, за якою знаходиться довжина масиву address p>
виконання
функції призводить до встановлення віртуального з'єднання p>
nsd
- Новий дескриптор програмного гнізда, який повинен використовуватися при
роботі через дане з'єднання p>
по
адресою addrlen пом?? тається реальний розмір масиву даних, які записані по
адресою address p>
Передача
і отримання даних через програмні гнізда з встановленим віртуальним
з'єднанням: p>
count = send (sd, msg, length,
flags); p>
count = recv (sd, buf, length,
flags); p>
В
send: p>
msg
вказує на буфер з даними, які потрібно послати p>
length
- Довжина цього буфера p>
flags
== MSG_OOB позачергова посилка даних p>
В
recv: p>
buf
вказує на буфер, в який слід помістити приймаються дані p>
length
- Максимальна довжина цього буфера p>
flags
== MSG_PEEK перепис повідомлення в користувальницький буфер без його видалення з
системних буферів p>
Замість
send і recv можна використовувати read і write p>
виконуються
аналогічно send і recv p>
Для
здійснення та отримання повідомлень в дейтаграмним режимі: p>
count = sendto (sd, msg, length,
flags, socknm, socknlen); p>
count = recvfrom (sd, buf, length,
flags, socknm, socknlen); p>
сенс
параметрів sd, msg, buf і lenght аналогічний змістом однойменних параметрів
функцій send і recv p>
socknm
і socknlen функції sendto задають ім'я програмного гнізда, в яке надсилається повідомлення
p>
можуть
бути опущені, якщо до цього викликалася функція connect p>
параметри
socknm і socknlen функції recvfrom дозволяють серверу отримати ім'я того, хто вислав
повідомлення процесу-клієнта p>
Негайна
ліквідація встановленого з'єднання: p>
shutdown (sd,
mode); p>
негайно
зупинити комунікації p>
з
боку посилає процесу p>
з
приймаючої сторони процесу p>
з
обох сторін p>
в
залежно від значення параметра mode p>
shutdown
відрізняються від close: p>
виконання
close останньою "пригальмовується" до закінчення спроб системи
доставити вже відправлені повідомлення p>
shutdown
розриває з'єднання, але не ліквідує дескриптори раніше з'єднаних гнізд p>
для
ліквідації потрібно виклик close p>
Потоки
(streams) p>
UNIX System V p>
бібліотека TLI (Transport Layer Interface) p>
транспортний
сервіс на основі стеку протоколів TCP/IP p>
Дозволяють
організовувати різноманітні види комунікації процесів p>
Різноманіття
і складність набору функцій бібліотеки TLI p>
Належить
до теми реалізацій Семирівнева моделі ISO/OSI p>
Список літератури h2>
Для
підготовки даної роботи були використані матеріали з сайту http://www.citforum.ru/
p>