- •Лабораторна робота №1
- •Основні положення. Поняття операційної системи.
- •Завдання
- •Лабораторна робота № 2.
- •Основні положення
- •1. Поняття файлу
- •2. Поняття файлової системи
- •3. Типи файлів
- •4. Імена файлів
- •5. Організація інформації у файловій системі
- •6. Загальні відомості про файлові операції
- •Приклад виконання завдання.
- •Завдання
- •Контрольні питання
- •Лабораторна робота № 3
- •Основні положення.
- •1. Каталоги
- •2. Операції над каталогами
- •3. Робота з каталогами в posix
- •Приклад виконання завдання
- •Завдання
- •Контрольні питання
- •Лабораторна робота № 4
- •Основні положення.
- •Створення процесу.
- •Ієрархія процесів.
- •Реалізація процесів.
- •4. Системні виклики для роботи з процесами
- •Приклад виконання завдання
- •Завдання
- •Контрольні питання
- •Лабораторна робота № 5
- •Основні положення
- •1. Застосування каналів.
- •Приклади виконання завдань
- •Завдання
- •Контрольні питання
- •Лабораторна робота № 6
- •Основні положення.
- •1. Черга повідомлень.
- •2. Створення черг повідомлень.
- •Прикдад виконання завдання
- •Завдання
- •Контрольні питання
Лабораторна робота № 6
Тема: Повідомлення як засіб міжпроцесної взаємодії.
Мета роботи : навчитися організовувати обмін даними між процесами з використанням повідомлень.
Основні положення.
Як зазначалося вище (лабораторна робота № 5), одним із засобів взаємодії процесів є повідомлення. Особливість цього методу полягає в тому, що він не ґрунтується на спільно використовуваних даних. Засоби передавання повідомлень ґрунтуються на обміні повідомленнями – фрагментами даних змінної довжини.
Для таких об'єктів IPC, як черги повідомлень, процес призначення імен є більш складним, ніж просто вказівка імені файлу. Ім'я для цих об'єктів називається ключем і генерується функцією ftok( ) із двох компонентів – імені файлу і відмінного від нуля ідентифікатора проекту.
В якості імені файлу можна використовувати маршрутне ім'я деякого файлу, яке відоме взаємодіючим процесам. Наприклад, це може бути ім'я програми-сервера. Важливо, щоб цей файл існував на момент створення ключа. Небажано використовувати ім'я файлу, який створюється і видаляється в процесі роботи додатку, оскільки при генерації ключа використовується номер індексного дескриптора файлу.
Вказаний засіб IPC має свій унікальний ідентифікатор, який використовується ядром ОС для роботи з об'єктом. Будь-яка черга повідомлень може мати той же числовий ідентифікатор, що і розділювана пам'ять, але будь-які дві черги повідомлень повинні мати різні ідентифікатори.
Черга повідомлень зберігається у вигляді внутрішнього однонаправленого зв'язаного списку в адресному просторі ядра. Для кожної черги ядро створює заголовок черги (msgid), де міститься інформація про права доступу до черги (msgperm), її поточний стан, а також вказівники на перше і останнє повідомлення, що зберігаються у вигляді зв'язаного списку.
1. Черга повідомлень.
Для забезпечення можливості обміну повідомленнями між процесами механізм черг підтримується наступними системними викликами:
msgget() для створення нової черги повідомлень чи отримання дескриптора існуючої черги;
msgsnd() для розміщення повідомлення у вказану чергу повідомлень;
msgrcv() для вибірки повідомлення із черги повідомлень;
msgctl() для виконання ряду керуючих дій.
Прототипи перерахованих системних викликів описані у файлах
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msgid, struct msgbuf *msgp, int msgsz, int msgflg);
int msgrcv(int msgid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg).
Тут msgid є дескриптором об'єкту, отриманого в результаті виклику msgget() у відповідь на ключ key і набір прапорців; при цьому ядро або створює нову чергу повідомлень і повертає користувачу ідентифікатор створеної черги, або знаходить елемент таблиці черг повідомлень, що містить вказаний ключ, і повертає відповідний ідентифікатор черги.
int msgqid = msgget(key_t key, int msgflg).
Для розміщення повідомлення в чергу використовується системний виклик msgsnd():
int msgsnd(int msgid, struct msgbuf *msgp, int msgsz, int msgflg);
де msg – це вказівник на структуру довжиною sz, що містить визначений користувачем цілий тип повідомлення і символьний масив-повідомлення.
Структура msg має вигляд:
struct msg {
long mtype; /* тип повідомлення */
char mtext[SOMEVALUE]; /* текст повідомлення (SOMEVALUE – будь-яке */};
Параметр flag визначає дії ядра при виході за межі допустимих розмірів внутрішньої буферної пам'яті.
Умовами успішного розміщення повідомлення в чергу є:
наявність у процесу прав на запис в дану чергу повідомлень;
не перевищення довжиною повідомлення заданої системою верхньої межі;
додатнє значення вказаного у повідомленні типу повідомлення.
Якщо ж виявиться, що нове повідомлення неможливо буферизувати в ядрі по причині перевищення верхньої межі сумарної довжини повідомлень, що знаходяться в даній черзі повідомлень (при цьому прапорець IPC_NOWAIT відсутній), то процес, який звернувся, відкладається («присипляється») до того часу, поки черга повідомлень не розвантажиться процесами, які чекають отримання повідомлень.
Для прийому повідомлень використовується системний виклик msgrcv():
int msgrcv(int msgid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg).
Системний виклик msgctl()
int msgctl (int msgqid, int command, struct msqid_ds *msg_stat)
використовується
для опитування стану описувача черги повідомлень (command = IPC_STAT) і розміщення його в структуру msg_stat;
для зміни його стану (command = IPC_SET), наприклад, зміни прав доступу до черги;
для знищення вказаної черги повідомлень (command = IPC_RMID).
