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

2. Використання каналів

Канал - це засіб зв'язку стандартного висновку одного процесу зі стандартним уведенням іншого. Канали - це найстарший з інструментів IPC, що існує приблизно із часу появи самих ранніх версій оперативної системи UNIX. Вони надають метод однобічних комунікацій (звідси термін half-duplex) між процесами.

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

in <----- in

Parent Process Kernel Child Process

out <----- out

Рисунок 4 – Конструкція каналу

Створення каналів виконується з використанням функції

#include <unistd.h> int pipe(int *filedes);

Функція повертає два дескриптори:

filedes[0] - для запису;

filedes[1] - для читання.

Обмін інформацією виконується з використання функцій запису й читання API. Канали використовуються для родинних процесів.

Незалежні процеси можуть використовувати іменовані канали. Такі канали створюються функцією.

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/fcntl.h>

#include <unistd.h>

int mknod(const char *pathname, mode_t, dev_t dev);

Перший параметр специфицирует ім'я створюваного каналу, параметр mode задає права доступу й тип (для іменованого каналу використовується значення S_IFIFO). Третій параметр ігнорується. Функція повертає ознаку нормального завершення - 0, при помилці вертається значення -1.

Знищення каналу виконується по функції

int unlink(const char *pathname)

Наступний приклад ілюструє передачу короткого повідомлення між родительски й дочірнім процесом.

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <errno.h>

#include <sys/types.h>

int main() {

pid_t childPid;

int flds[2], status;

char buf[]="Message";

// Створення каналу

if (pipe(flds) == -1)

{ perror("Pipe"); exit(1); }

// Розгалуження процесів

switch (childPid=fork())

{ case -1: perror("fork");

exit(2);

case 0:

close(flds[0]);

//Нащадок

printf("Child process %d\n", getpid()); write(flds[1], buf,

strlen(buf));

close(flds[1]); exit(0); }

// Процес - батько

printf("Process %d\n", getpid());

close(flds[1]);

read(flds[0], buf, 80);

printf("String -> %s\n", buf);

close(flds[0]);

wait(&status);

return status;

}

На початку програми створюється канал і формуються два ідентифікатори файлів для цього каналу (flds[0] і flds[1]). Будемо вважати, що в батьківського процесу flds[0] використовується для прийому даних, тому на початку секції батьківського процесу необхідно закрити канал, пов'язаний з файловим ідентифікатором flds[1]. У породженому процесі закривається канал з ідентифікатором flds[0].

Наступний приклад ілюструє обмін даними між двома незалежними процесами через іменований канал.

Перша програма служить сервером, вона створює іменований канал по функції

mkfifo(NAME, S_IFIFO|S_IRWXU|S_IRWXG|S_IRWXO).

Як перший параметр використовується рядок, певна константою NAME. Другий параметр являє собою комбінацію ключів, що визначають дозвіл повних прав доступу для всіх категорій користувачів. Після створення каналу на стороні сервера він відкривається в режимі читання. Після приходу повідомлення, текст цього повідомлення виводиться на екран і канал закривається. Наприкінці програми функцією unlink(NAME) канал знищується. Відкриття й знищення каналу виконуються з використанням того самого ім'я (константа NAME зі значенням "sfifo.cc").

/* Сервер. Створює FIFO і очікує повідомлення */

#include <iostream.h>

#include <stdio.h>

#include <errno.h>

#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#define NAME "sfifo.cc"

int main() {

int fd;

char buf[80];

unlink(NAME);

if(mkfifo(NAME, S_IFIFO|S_IRWXU|S_IRWXG|S_IRWXO)) {

perror("Помилка FIFO");

return 1; }

if((fd=open(NAME, O_RDONLY))==-1) {

perror("Помилка відкриття файлу сервера"); }

read(fd, buf, sizeof(buf));

cout<<"Отримано->"<<buf<<endl; close(fd);

unlink(NAME);

return 0;

}

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

/* Клієнт */

#include <iostream.h>

#include <stdio.h>

#include <errno.h>

#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <string.h>

#include <sys/stat.h>

#define NAME "sfifo.cc"

int main() {

char text[80];

int fd;

cout<<"Увести ссобщение"<<endl;

cin>>text;

if((fd=open(NAME, O_WRONLY))==-1) {

perror("Помилка відкриття клієнта");

return 1; }

write(fd, text, strlen(text)); close(fd); return 0;

}

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