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

Створення черги повідомлень або доступ до вже існуючої. Системний виклик msgget()

Для створення черги повідомлень, асоційованої з певним ключем, або доступу по ключу до вже існуючої черги використовується системний виклик msgget(), є аналогом системних викликів shmget() для пам'яті, що розділяється, і semget() для масиву семафорів, який повертає значення IPC-дескриптора для цієї черги. При цьому існують ті ж способи створення і доступу, що і для пам'яті, що розділяється або семафорів.

Системний виклик msgget()

#include <types.h>

#include <ipc.h>

#include <msg.h>

int msgget(key_t key, int msgflg);

Опис системного виклику

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

Параметр key є ключем System V IPC для черги повідомлень, тобто фактично її ім'ям з простору імен System V IPC. Як значення цього параметра може бути використано значення ключа, одержане за допомогою функції ftok(), або спеціальне значення IPC_PRIVATE. Використовування значення IPC_PRIVATE завжди приводить до спроби створення нової черги повідомлень з ключем, який не співпадає із значенням ключа жодної з вже існуючих черг і не може бути одержаний за допомогою функції ftok() ні при одній комбінації її параметрів.

Параметр msgflg – прапори – грає роль тільки при створенні нової черги повідомлень і визначає права різних користувачів при доступі до черги, а також необхідність створення нової черги і поведінка системного виклику при спробі створення. Він є деякою комбінацією (за допомогою операції побітове або – "|") наступних приречених значень і вісімкових прав доступу:

  • IPC_CREAT — якщо черги для вказаного ключа не існує, вона повинна бути створена;

  • IPC_EXCL — застосовується спільно з прапором IPC_CREAT. При сумісному їх використовуванні і існуванні масиву з вказаним ключем доступ до черги не проводиться і констатується помилкова ситуація, при цьому змінна errno, описана у файлі <errno.h>, прийме значення EEXIST;

  • 0400 — дозволено читання для користувача, що створив чергу;

  • 0200 — дозволений запис для користувача, що створив чергу;

  • 0040 — дозволено читання для групи користувача, що створив чергу;

  • 0020 — дозволений запис для групи користувача, що створив чергу;

  • 0004 — дозволено читання для всієї решти користувачів;

  • 0002 — дозволений запис для всієї решти користувачів;

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

ipcs -l

Значення, що повертається

Системний виклик повертає значення дескриптора System V IPC для черги повідомлень при нормальному завершенні і значення -1 при виникненні помилки.

Реалізація примітивів send і receive. Системні виклики msgsnd() і msgrcv()

Для виконання примітиву send використовується системний виклик msgsnd(), копіюючий призначене для користувача повідомлення в чергу повідомлень, задану IPC-дескриптором. При вивченні опису цього виклику звернете особливу увагу на наступні моменти:

  • Тип даних struct msgbuf не є типом даних для призначених для користувача повідомлень, а є лише шаблоном для створення таких типів. Користувач сам повинен створити структуру для своїх повідомлень, в якій першим полем винна бути змінна типу long, що містить позитивне значення типу повідомлення.

  • Як третій параметр – довжини повідомлення – указується не вся довжина структури даних, відповідної повідомленню, а тільки довжина корисної інформації, тобто інформації, розташованої в структурі даних після типу повідомлення. Це значення може бути і рівним 0 у разі, коли вся корисна інформація полягає в самому факті приходу повідомлення (повідомлення використовується як сигнальний засіб зв'язку).

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

Системний виклик msgsnd()

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int msgsnd(int msqid, struct msgbuf *ptr

int length, int flag);

Опис системного виклику

Системний виклик msgsnd призначений для приміщення повідомлення в чергу повідомлень, тобто є реалізацією примітиву send.

Параметр msqid є дескриптором System V IPC для черги, в яку відправляється повідомлення, тобто значенням, яке повернув системний виклик msgget() при створенні черги або при її пошуку по ключу.

Структура struct msgbuf описана у файлі <sys/msg.h> як

struct msgbuf {

long mtype;

char mtext[1];

};

Вона є деяким шаблоном структури повідомлення користувача. Повідомлення користувача – це структура, перший елемент якої обов'язково має тип long і містить тип повідомлення, а далі слідує інформативна частина теоретично довільної довжини (практично в Linux вона обмежена розміром 4080 байт і може бути ще зменшена системним адміністратором), що містить власне суть повідомлення. Наприклад:

struct mymsgbuf {

long mtype;

char mtext[1024];

} mybuf;

При цьому інформація зовсім не зобов'язана бути текстовою, наприклад:

struct mymsgbuf {

long mtype;

struct {

int iinfo;

float finfo;

} info;

} mybuf;

Тип повідомлення повинен бути строго позитивним числом. Дійсна довжина корисної частини інформації (тобто інформації, розташованої в структурі після типу повідомлення) повинна бути передана системному виклику як параметр length. Цей параметр може бути рівний і 0, якщо вся корисна інформація полягає в самому факті наявності повідомлення. Системний виклик копіює повідомлення, розташоване за адресою, на яку указує параметр ptr, в чергу повідомлень, задану дескриптором msqid.

Параметр flag може приймати два значення: 0 і IPC_NOWAIT. Якщо значення прапора рівне 0, і в черзі не вистачає місця для того, щоб помістити повідомлення, то системний виклик блокується до тих пір, поки не звільниться місце. При значенні прапора IPC_NOWAIT системний виклик в цій ситуації не блокується, а констатує виникнення помилки зі встановленням значення змінної errno, описаної у файлі <errno.h>, рівним EAGAIN.

Значення, що повертається

Системний виклик повертає значення 0 при нормальному завершенні і значення -1 при виникненні помилки.

Примітив receive реалізується системним викликом msgrcv(). При вивченні опису цього виклику потрібно звернути особливу увагу на наступні моменти:

  • Тип даних struct msgbuf, як і для виклику msgsnd(), є лише шаблоном для призначеного для користувача типу даних.

  • Спосіб вибору повідомлення (див. розділ "Черги повідомлень в UNIX як складова частина System V IPC" поточного семінару) задається нульовим, позитивним або негативним значенням параметра type. Точне значення типу вибраного повідомлення можна визначити з відповідного поля структури, в яку системний виклик скопіює повідомлення.

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

  • Вибране повідомлення віддаляється з черги повідомлень.

  • Як параметр length указується максимальна довжина корисної частини інформації, яка може бути розміщена в структурі, адресованій параметром ptr.

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

Системний виклик msgrcv()

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int msgrcv(int msqid, struct msgbuf *ptr

int length, long type, int flag);

Опис системного виклику

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

Параметр msqid є дескриптором System V IPC для черги, з якої повинно бути одержано повідомлення, тобто значенням, яке повернув системний виклик msgget() при створенні черги або при її пошуку по ключу.

Параметр type визначає спосіб вибірки повідомлення з черги таким чином

Спосіб вибірки

Значення параметра type

В порядку FIFO, незалежно від типу повідомлення

0

В порядку FIFO для повідомлень з типом n

n

Першим вибирається повідомлення з мінімальним типом, що не перевищує значення n, що прийшло раніше всіх інших повідомлень з тим же типом

-n

Структура struct msgbuf описана у файлі <sys/msg.h> як

struct msgbuf {

long mtype;

char mtext[1];

};

Вона є деяким шаблоном структури повідомлення користувача. Повідомлення користувача – це структура, перший елемент якої обов'язково має тип long і містить тип повідомлення, а далі слідує інформативна частина теоретично довільної довжини (практично в Linux вона обмежена розміром 4080 байт і може бути ще зменшена системним адміністратором), що містить власне суть повідомлення. Наприклад:

struct mymsgbuf {

long mtype;

char mtext[1024];

} mybuf;

При цьому інформація зовсім не зобов'язана бути текстовою, наприклад:

struct mymsgbuf {

long mtype;

struct {

int iinfo;

float finfo;

} info;

} mybuf;

Параметр length повинен містити максимальну довжину корисної частини інформації (тобто інформації, розташованої в структурі після типу повідомлення), яка може бути розміщена в повідомленні.

У разі успіху системний виклик копіює вибране повідомлення з черги повідомлень за адресою, вказаною в параметрі ptr, одночасно видаляючи його з черги повідомлень.

Параметр flag може приймати значення 0 або бути якою-небудь комбінацією прапорів IPC_NOWAIT і MSG_NOERROR. Якщо прапор IPC_NOWAIT не встановлений і черга повідомлень порожня або в ній немає повідомлень із замовленим типом, то системний виклик блокується до появи запитаного повідомлення. При встановленні прапора IPC_NOWAIT системний виклик в цій ситуації не блокується, а констатує виникнення помилки зі встановленням значення змінної errno, описаної у файлі <errno.h>, рівним EAGAIN. Якщо дійсна довжина корисної частини інформації у вибраному повідомленні перевищує значення, вказане в параметрі length і прапор MSG_NOERROR не встановлений, то вибірка повідомлення не проводиться, і фіксується наявність помилкової ситуації. Якщо прапор MSG_NOERROR встановлений, то в цьому випадку помилки не виникає, а повідомлення копіюється в скороченому вигляді.

Значення, що повертається

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

Максимально можлива довжина інформативної частини повідомлення в операційній системі Linux складає 4080 байт і може бути зменшена при генерації системи. Поточне значення максимальної довжини можна визначити за допомогою команди

ipcs -l