Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы(ОС) / Lab6 / LabOS_6.doc
Скачиваний:
58
Добавлен:
17.04.2013
Размер:
91.65 Кб
Скачать

7

Лабораторная работа по курсу "Операционные системы" Межпроцессное взаимодействие в ос Linux

Цель работы: научиться использовать каналы и именованные каналы для межпроцессного взаимодействия в ОС Linux.

I. Каналы (unnamed pipes)

Неименованный канал, или просто канал, - это однонаправленный канал связи в ОС UNIX. Каждый канал имеет два конца: входной (для записи, upstream end) и выходной (для чтения, downstream end). Каждый из двух концов канала имеет свой собственный дескриптор, являющийся целым числом, как и дескриптор файла. Оба дескриптора создаются при создании канала системным вызовом pipe(). Используя канал, один процесс может записывать данные во входной конец канала, а другой процесс может читать эти данные из выходного конца канала.

Неименованные каналы обычно используются для обмена сообщениями между связанными процессами (например, между двумя дочерними процессами, имеющими одного и того же родителя). Через канал возможно взаимодействие между родителем и его дочерним процессом, между дедом и внуком и т.п. С логической точки зрения канал является специальным файлом, и если канал был создан каким-либо процессом, то он может использоваться любыми процессами в группе, включая процесс-создатель и всех его потомков.

В команде оболочки канал создается при помощи символа "|" (см. лабораторную работу 1).

В программе неименованный канал создается при помощи системного вызова pipe():

ret = pipe (fd);

где ret - код возврата целого типа, fd - массив int fd[2] из двух элементов, в который записываются значения в результате этого системного вызова. Системный вызов pipe() возвращает 0 в случае успеха и -1 в случае ошибки.

Если системный вызов pipe() завершился успешно, то в первый элемент массива, fd[0], записывается дескриптор выходного конца созданного канала (для чтения), и в fd[1] - дескриптор входного конца (для записи).

В этой части лабораторной работы необходимо создать неименованный канал в начале работы родительского процесса, затем создать два дочерних процесса. Один из этих дочерних процессов будет выполнять какую-либо команду оболочки (например, ls -l /home/student) и записывать результаты работы во входной конец канала. Другой дочерний процесс (выполняющий, например, команду sort) будет получать данные из выходного конца того же канала. Таким образом, результат выполнения этих двух дочерних процессов будет идентичен выполнению последовательности двух команд оболочки (см. рис.1):

ls -l /home/student | sort

где "|" - символ операции канала в оболочке.

Задание 1.

1.1. Создайте отдельный подкаталог для лабораторной работы. Наберите приведенный ниже текст программы pipework.c (текст программы имеется в папке Methodic/…) и создайте для нее исполняемый файл. (На рис. 2 приведена структура программы.)

/* pipework.c A program to experiment with an unnamed pipe */

#include <stdio.h>

#include <unistd.h>

main ()

{

int fd[2]; /* Array of two descriptors for an unnamed pipe */

int pid; /* Variable for a process identifier */

/* A pipe should be created before any fork() */

/* Do you understand why? */

if (pipe(fd) < 0)

{perror ("PIPE CREATION ERROR");

exit (1);

}

pid = fork (); /* Parent: creating the first child process */

if (pid == 0) /* The first child process starts here */

{

dup2 (fd[0],0); /*Standard input will be taken from the downstream of the pipe*/

close (fd[1]); /*Upstream end of the pipe is closed for this process(not used)*/

execlp ("sort", "sort", 0); /* Running “sort”command taking input from the pipe */

}

else /* Here the parent process continues */

pid = fork (); /* Parent: creating the second child process */

if (pid == 0) /* The second child process starts here */

{dup2 (fd[1],1); /* Standard output will be put to the upstream end of the pipe */

close (fd[0]); /* Downstream end is closed for this process (not used) */

execlp ("ls", "ls", "-l", "/home/student", 0);

/*Running the command “who” which outputs to the pipe*/

}

else /* Parent process closes for itself both ends of the pipe

and waits for children to terminate */

{

close (fd[0]);

close (fd[1]);

wait (0);

wait (0);

}

}

Примечание. После вызова библиотечной функции dup2(fd1, fd2) файловый дескриптор fd2 будет ссылаться на тот же файл, что и дескриптор fd1. Если fd2 ссылается на уже открытый файл, то этот файл сначала будет закрыт. (См. man dup2.) Таким образом, dup2(fd1, 0) позволяет перенаправить стандартный ввод в файл fd1.

1.2. Запустите эту программу и сравните результаты с результатами следующих команд оболочки:

ls -l /home/student и

ls -l /home/student | sort

1.3. Замените в исходном тексте программы оператор (дайте этой программе имя pipework1.c)

execlp ("ls", "ls", "-l", "/home/student", 0);

несколькими системными вызовами write(), которые запишут в канал последовательность слов (например, “this\n”, “is\n”, “a\”, “message\n”, ‘from\n”, “sending\n”, “process\”). Для записи этих слов в канал следует использовать системный вызов write() так же, как и для обычного файла, указывая дескриптор fd[1]. После записи всех слов в канал закройте fd[1] и завершите процесс (exit()). Выполните программу.

Примечание. Для этой модификации оператор dup2(fd[1],1); НЕ НУЖЕН, его следует убрать.

1.4. Замените в программе из задания 1.3 оператор (дайте этой программе имя pipework2.c)

execlp ("sort", "sort", 0);

фрагментом, в котором читаются слова из канала и выводятся на стандартное устройство вывода (т.е. на экран). Для чтения данных из канала следует использовать системный вызов read() как и для обычного файла, указывая дескриптор fd[0]. После чтения и печати всех слов закройте fd[0] и завершите процесс (exit()).

Замечание. Для этой модификации оператор dup2(fd[0],0); НЕ НУЖЕН, его следует убрать.

1.4. В общем случае читать из канала могут несколько процессов; писать в канал также могут несколько процессов. Напишите программу pipework3.c, которая создает три дочерних процесса. Два из них записывают в канал по одному сообщению каждый, а третий дочерний процесс читает эти сообщения из канала и распечатывает их.

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

1.6. Запишите результаты работы всех программ и объясните их работу.

Соседние файлы в папке Lab6