Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
PR_СП_лабы_11.doc
Скачиваний:
7
Добавлен:
22.04.2019
Размер:
755.71 Кб
Скачать

Методичні вказівки

1. Загальні відомості

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

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

  • крім того, тому що кожне повідомлення має тип (на схемі - буква поруч із номером повідомлення), те цю чергу можна розглядати, як суперпозицію черг, пов'язану з повідомленнями одного типу.

Рисунок 5 - Черга повідомлень

Система IPC дозволяє створювати поділюваний ресурс, називаний “черга повідомлень” - таких черг може бути довільна кількість. Можна створити черга, підключитися до неї, послати повідомлення, прийняти повідомлення, знищити черга й т.д.

2. Використання повідомлень

Для ідентифікації повідомлень можна використовувати ключі, які генеруються в системі при виклику функції

key_t ftok(char *filename, char proj);

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

Для обміну використовуються черги повідомлень. Черга створюється функцією

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int msgget(key_t key, int msgflg);

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

Посилка й прийом повідомлень організуються при виклику функцій

int msgsnd(int msgid, struct msgbuf *msgp, int msgsz, int msgflg);

и

int msgrcv(int msgid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);

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

struct msgbuf {

long mtype; /* тип повідомлення */

char mtext[]; /* покажчик на буфер повідомлення */ };

Параметр msgsz визначає довжину повідомлення. При значенні параметра msgflg=0 процес може блокуватися доти, поки функція не буде виконана. Параметр msgtyp задає правила вибору повідомлення із черги. При нульовому значенні параметра із черги витягає саме старе повідомлення будь-якого типу. Позитивне значення визначає прийом самого старого повідомлення зазначеного типу.

Видалення черги із системи виробляється при виклику функції

int msgctl(int msgid, int cmd, struct msgbuf *msgp);

при значенні параметра cmd рівному IPC_RMID , третій параметр при цьому встановлюється в значення NULL.

Розглянемо дві програми. Перша буде виконувати роль сервера. Вона створює чергу повідомлень і посилає другій програмі - клієнтові рядок уведеного із клавіатури тексту. Для попереднього формування повідомлення створюється структура buf по шаблоні mybuf. По запиті із клавіатури водиться рядок тексту (рядок text).

Далі формується ключ. Вихідним рядком для формування ключа служить ім'я файлу з текстом програми "smess.c". Черга повідомлень створюється по отриманому раніше ключі із правами доступу для користувача на читання й запис, для інших дозволене тільки читання із черги.

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

Трансляція сервера виробляється по командному рядку cc smess.c –o smess. У результаті компіляції й компонування формується виконується файл, щоМ, smess.

/* Сервер роботи з повідомленнями */

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int main()

{key_t key;

struct mybuf { long mtype; char mtext[81];} ;

struct mybuf buf;

int fd;

char text[81];

int textLen;

printf("Увести текст\n");

gets(text);

textLen=strlen(text);

if ((key=ftok("smess.c",0))==-1 )

{perror("Помилка створення ключа"); return 1; }

if ((fd=msgget(key, IPC_CREAT|0644))==-1)

{perror("Помилка створення черги");return 1; }

strncpy(buf.mtext, text, textLen); buf.mtype=1L;

if((fd=msgsnd(fd, &buf, textLen,0))==-1)

{perror("Помилка посилки повідомлення");return 1; }

return 0;

}

Програма - клієнт розміщається у файлі cmess.c.

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

Для прийому повідомлення у функції msgrcv() задаються перші два параметри, значення прапорів і режиму можна встановити рівними нулю. Текст отриманого повідомлення виводиться на консоль.

/* Клієнт роботи з повідомленнями */

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int main()

{key_t key;

struct mybuf {long mtype; char mtext[81]; } ;

struct mybuf buf; int fd; char text[81]; int textLen;

if((key=ftok("smess.c",0))==-1 )

{perror("Помилка створення ключа"); return 1; }

if((fd=msgget(key, 0))==-1)

{perror("Помилка створення черги"); return 1; }

if((fd=msgrcv(fd, &buf, 80, 0, 0))==-1)

{ perror("Помилка прийому повідомлення"); return 1; }

printf("Отриманий текст -> %s\n",buf.mtext);

return 0;

}

Програма - клієнт запускається на окремій консолі. Для переходу на нову консоль необхідно нажати комбінацію клавіш Alt+Fn, де n - номер функціональної клавіші. Після створення консолі на ній виробляється звичайна реєстрація користувача. На першій консолі запускається клієнт (командний рядок ./cmess). На другій консолі запускається сервер (./smess).

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