Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_по_ОС / ТОС_9_м_пр_слайды.doc
Скачиваний:
42
Добавлен:
03.03.2016
Размер:
14.52 Mб
Скачать

Int pipe(int *fieldes);

который возвращает два файловых дескриптора

fildes [0] для записи в канал и

fildes[1] для чтения из канала.

Теперь, если один процесс за­писывает данные в fildes[0], другой сможет получить эти данные из fildes[1] .

Вопрос только в том, как другой процесс сможет получить сам файловый дескриптор fildes[ 1 ]?

Дочерний про­цесс наследует и разделяет все назначенные файловые дескрипторы роди­тельского. То есть доступ к дескрипторам fildes канала может получить сам процесс, вызвавший pipe(), и его дочерние процессы.

В этом заключается серьезный недостаток каналов, поскольку они могут быть исполь­зованы для передачи данных только между родственными процессами. Каналы не могут использоваться в качестве средства межпроцессного взаимодействия между независимыми процессами.

в приведенном примере процессы cat() и wc() создаются процессом shell и являются родственными.

Рис. 3.17. Создание канала между задачами саt(1) и wc(1)

FIFO

Firt In First Out (пер­вый вошел — первый вышел).

FIFO очень похожи на каналы, поскольку являются однонаправленным средством передачи данных, причем чтение данных происходит в порядке их записи.

в отличие от программ­ных каналов, FIFO имеют имена, которые позволяют независимым про­цессам получить к этим объектам доступ.

Поэтому иногда FIFO также на­зывают именованными каналами.

FIFO являются средством UNIX System V и не используются в BSD. Впервые FIFO были представлены в System III, однако они до сих пор не документированы и поэтому мало используются.

FIFO является отдельным типом файла в файловой системе UNIX (ls -l покажет символ р в первой позиции

Для создания FIFO используется системный вызов mknod():

Int mknod(char *pathname, int mode, int dev);

где pathname — имя файла в файловой системе (имя FIFO),

mode — флаги владения, прав доступа и т. д.,

dev - при создании FIFO игнорируется.

FIFO м.б. создан и из командной строки shell:

$ mknod name p

После создания FIFO может быть открыт на запись и чтение, причем за­пись и чтение могут происходить в разных независимых процессах.

Правила работы канала FIFO :

1. При чтении меньшего числа байтов, чем находится в канале или FIFO, возвращается требуемое числобайтов, остаток сохраняется для последующих чтений.

2. При чтении большего числа байтов, чем находится в канале или FIFO, возвращается доступное число байтов. Процесс, читающий из канала, должен соответствующим образом обработать ситуацию, когда прочитано меньше, чем заказано.

3. Если канал пуст и ни один процесс не открыл его на запись, при чтении из канала будет получено 0 байтов. Если один или более процес­сов открыли канал для записи, вызов read() будет заблокирован до появления данных .

4. Запись числа байтов, меньшего емкости канала или FIFO, гарантированно атомарно. Это означает, что в случае, когда несколько процессов одновременно записывают в канал, порции данных от этих процессов не перемешиваются.

5. При записи большего числа байтов, чем это позволяет канал или FIFO, вызов write() блокируется до освобождения требуемого места, При этом атомарность операции не гарантируется. Если процесс пы­тается записать данные в канал, не открытый ни одним процессом на чтение, процессу генерируется сигнал SIGPIPE, а вызов write() воз­вращает 0 с установкой ошибки (errno=EPIPE) (если процесс не уста­новил обработки сигнала SIGPIPE, производится обработка по умолчанию — процесс завершается).

пример приложения клиент-сервер, использующего FIFO для обмена данными. Следуя традиции, кли­ент посылает серверу сообщение "Здравствуй, Мир!", а сервер выводит это сообщение на терминал.

Сервер:

#include <sys/types.h>

#include <sys/stat.h>

#define FIFO “fifo.1”

#define MAXBUFF 80

main()

{

int readfd, n;

char buff[MAXBUFF]; /*буфер для чтения данных из FIFO*/

/*Создадим специальный файл FIFO с открытыми для всех правами доступа на чтение и записаь*/

if(mknod(FIFO, S_FIFO | 0666, 0)<0

{

printf(“Невозможно создать FIFO\n”); exit(1); }

/*Получим доступ к FIFO*/

if ((readfd = open(FIFO, O_RDONLY))<0)

{

printf(“Невозможно открыть FIFO\n”);

exit(1); }

/*Прочитаем сообщение (“здравствуй, мир”) и выведем его на экран*/

while

((n = read(readfd, buff, MAXBUFF)) > 0)

if(write(1, buff, n) != n)

{

printf(“Ошибка вывода\n”); exit(1); }

/*Закроем FIFO, удаление FIFO – дело клиента*/

close(readfd);

exit(0);

}

Клиент:

#include <sys/types.h>

#include <sys/stat.h>

/*Соглашение об имени FIFO*/

#define FIFO “fifo.1”

main()

{

int writefd, n;

/*Получим доступ к FIFO*/

if ((writefd = open(FIFO, WRONLY)) < 0)

{

printf(“Невозможно открыть

FIFO\n”); exit(1); }

/*Передадим сообщение серверу FIFO*/

if(

write(writefd,”Здравствуй, Мир!\n”, 18) != 18)

{

printf(“Ошибка записи\n”); exit(1);}

/* Закроем FIFO */

close(writefd);

/* Удалим FIFO */

if(unlink(FIFO)<0 {

printf(“Невозможно удалить

FIFO\n”); exit(1); }

exit(0);

}

Идентификаторы и имена в IPC

Отсутствие имен у каналов делает их недоступными для независимых процессов.

Этот недостаток устранен у FIFO, которые имеют имена.

Другие средства межпроцессного взаимодействия, являющиеся более сложными, требуют дополнительных соглашений по именам и идентификаторам.

Множество возможных имен объектов конкретного типа межпроцессного взаимодействия называется пространством имен (name space).

Имена являются важным компонентом системы межпроцессного взаимодействия для всех объектов, кроме каналов, поскольку по зволяют различным процессам получить доступ к общему объекту.

именем FIFO является имя файла именованного канала. Используя услов­ленное имя созданного FIFO два процесса могут обращаться к этому объ­екту для обмена данными.

Для таких объектов IРС, как очереди сообщений, семафоры и разделяемая память, процесс назначения имени является более сложным, чем просто указание имени файла.

Имя для этих объектов называется ключом (key) и генерируется функцией ftok()

из двух компонентов — имени файла и идентификатора проекта:

#include<sys/types.h>

#include<sys/ipc.h>

key_t ftok(char *filename, char proj);

где filename - имя некоторого файла, извест­ное взаимодействующим процессам. Например, это может быть имя про­граммы-сервера. Важно, чтобы этот файл существовал на момент создания ключа.

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

Вновь созданный файл может иметь другой inode и впоследствии процесс, желающий иметь дос­туп к объекту, получит неверный ключ.

Пространство имен позволяет создавать и совместно использовать IРС не­родственным процессам. Однако для ссылок на уже созданные объекты используются идентификаторы, точно так же, как файловый дескриптор используется для работы с файлом, открытым по имени.

Каждое из перечисленных 1РС имеет свой уникальный дескриптор (идентификатор), используемый ОС (ядром) для работы с объектом. Уни­кальность дескриптора обеспечивается уникальностью дескриптора для каждого из типов объектов (очереди сообщений, семафоры и разделяемая память), т. е. какая-либо очередь сообщений может иметь тот же числен­ный идентификатор, что и разделяемая область памяти (хотя любые две очереди сообщений должны иметь различные идентификаторы).

Таблица 3.5. Идентификация объектов 1РС

Объект IРС

Пространс

тво имен

Дескриптор

Канал

Файловый

дескриптор

FIFO

Имя файла

Файловый

дескриптор

Очередь

сообщений

Ключ

Идентификатор

Семафор

Ключ

Идентификатор

Разделяемая

память

Ключ

Идентификатор

Работа с объектами IPC System V во многом сходна.

Для создания или по­лучения доступа к объекту используются соответствующие системные вы­зовы get:

mssget() для очереди сообщений,

semget() для семафора и

shmget() для разделяемой памяти.

Все эти вызовы возвращают дескриптор объекта в случае успеха и -1 в случае неудачи.

Функции get позволяют процессу получить ссылку на объект, которой по существу яв­ляется возвращаемый дескриптор, но не позволяют производить конкрет­ные операции над

Все функции get в качестве аргументов используют ключ key и флажки создания объекта ipcflag.

Остальные аргументы зависят от конкретного типа объекта.

Переменная ipcflag определяет права доступа к объекту PERM, а также указывает, создается ли новый объект или требу­ется доступ к существующему.

Последнее определяется комбинацией (или отсутствием) флажков IPC_CREAT и IPC_EXCL.

Права доступа к объекту указываются набором флажков доступа:

Комбинацией флажков можно добиться различных результатов:

Работа с объектами IPC System V во многом похожа на работу с файлами в UNIX.

Одним из различий является то, что файловые дескрипторы имеют значимость в контексте процесса, в то время как значимость дескрипторов объектов IPC распространяется на всю систему.

процессы, использующие одни объекты IPC, получат оди­наковые дескрипторы этого объекта.

Для каждого из объектов IPC ядро поддерживает соответствующую струк­туру данных, отличную для каждого типа объекта IPC (очереди сообще­ний, семафора или разделяемой памяти).

Общей у этих данных является структура ipc_perm, описывающая права доступа к объекту, подобно тому, как это делается для файлов.

Основные поля структуры ipc_perm:

uid Идентификатор владельца-пользователя объекта

gid Идентификатор владельца-группы объекта

cuid UID создателя объекта (эффективные идентификаторы)

cgid GID создателя объекта

mode Права доступа на чтение и запись для всех классов доступа (9 битов)

key Ключ объекта

Права доступа (как и для файлов) определяют возможные операции, кото­рые может выполнять над объектом конкретный процесс (получение дос­тупа к существующему объекту, чтение, запись и удаление).

Система не удаляет созданные объекты IPC даже тогда, когда ни один процесс не пользуется ими.

Удаление созданных объектов являет­ся обязанностью процессов, которым для этого предоставляются соответ­ствующие функции управления msgctl(), semctl(), shmctl().

С помощью этих функций процесс может получить и установить ряд полей внутри структур, поддерживаемых системой для объектов IРС, а также удалит созданные объекты.

Как и во многих других случаях использо­вания объектов IРС процессы предварительно должны "договориться", какой процесс и когда удалит объект. Чаще всего, таким процессом является сервер.

.