Назад | Оглавление | Вперед |
![]() |
Лабораторная работа №11Обмен данными между процессами с помощью неименованных программных каналовЦель работы: освоение неименованных программных каналов как способа обмена данными между процессами. |
Программный канал в Unix/Linux представляет собой одно из средств взаимодействия между процессами. Само название (pipe, дословно - трубка) достаточно точно передает смысл функционирования этого средства. Канал подобен трубопроводу, проложенному между двумя процессами, и по этому трубопроводу процессы могут пересылать друг другу данные. Подобно трубопроводу, канал имеет собственную емкость, данные, направленные в канал процессом-отправителем, не обязательно должны быть немедленно прочитаны процессом-получателем, но могут накапливаться в канале. Как и у трудобровода, емкость канала конечна, когда она будет исчерпана, запись в канал становится невозможной.
Операционные системы Unix/Linux представляеют в распоряжение программистов два вида каналов - именованные и неименованные. Работа с обоими видами во многом подобна работе с файлами.
Неименованный канал является средством взаимодействия между связанными процессами - родительским и дочерним. Родительский процесс создает канал при помощи системного вызова:
int pipe(int fd[2]);
Массив из двух целых чисел является выходным параметром этого системного вызова. Если вызов выполнился нормально, то этот массив содержит два файловых дескриптора. fd[0] является дескриптором для чтения из канала, fd[1] - дескриптором для записи в канал. Когда процесс порождает другой процесс, дескрипторы родительского процесса наследуются дочерним процессом, и, таким образом, прокладывается трубопровод между двумя процессами. Естественно, что один из процессов использует канал только для чтения, а другой - только для записи (сами представьте себе, что произойдет, если это правило будет нарушаться). Поэтому, если, например, через канал должны передаваться данные из родительского процесса в дочерний, родительский процесс сразу после запуска дочернего процесса закрывает дескриптор канала для чтения, а дочерний процесс закрывает дескриптор для записи. Если нужен двунаправленный обмен данными между процессами, то родительский процесс создает два канала, один из которых используется для передачи данных в одну сторону, а другой - в другую. После получения процессами дескрипторов канала для работы с каналом используются файловые системные вызовы:
int read(int pipe_fd, void *area, int cnt); int write(int pipe_fd, void *area, int cnt);
Первый аргумент этих вызовов - дескриптор канала, второй - указатель на область памяти, с которой происходит обмен, третий - количество байт. Оба вызова возвращают число переданных байт (или -1 - при ошибке).
Выполнение этих системных вызовов может переводить процесс в состояние ожидания. Это происходит, если процесс пытается читать данные из пустого канала или писать данные в переполненный канал. Процесс выходит из ожидания, когда в канале появляются данные или когда в канале появляется свободное место, соответственно.
При завершении использования канала процесс выполняет системный вызов:
int close(int pipe_fd);
Если родительский процесс, создавший канал, порождает несколько дочерних процессов, то все дочерние процессы подключены к другому концу канала. Если, например, родительский процесс выводит данные в канал, то они "достанутся" тому дочернему процессу, который раньше выполнит системный вызов read.
I. Проанализировать результат работы программы-примера.
II. Модифицировать программу, разработанную в лабораторной работе №9, в соответствии с индивидуальным заданием с учетом следующих требований:
Отчет по лабораторной работе оформить на украинском языке в соответсвии со следующими пунктами:
Пример выполнения основной части работы №11 приведен здесь.
Избранные системные вызовы Linux/Unix. Краткое описание.
Cправочник библиотечных функция языка С: часть 1, часть 2 (кодировка кириллица ibm866).
Назад | Оглавление | Вперед |