Системное программное обеспечение - Учебное пособие (Терехин А.Н.)

4.5       использование канала.

Пример использования канала в рамках одного процесса – копирование строк. Фактически осуществляется посылка данных самому себе.

#include <unistd.h>

#include <stdio.h>

int main(int argc, char **argv)

{

char *s = ”chanel”;

char buf[80];

int pipes[2];

pipe(pipes);

write(pipes[1], s, strlen(s) + 1);

read(pipes[0], buf, strlen(s) + 1);

close(pipes[0]);

close(pipes[1]);

printf(“\%s ”, buf);

return 0;

}

Рис. 15 Обмен через канал в рамках одного  процесса.

Чаще всего, однако, канал используется для обмена данными между несколькими процессами. При организации такого обмена используется тот факт, что при порождении сыновнего процесса посредством системного вызова fork() наследуется таблица файловых дескрипторов процесса-отца, т.е. все файловые дескрипторы, доступные процессу-отцу, будут доступны и процессу-сыну. Таким образом, если перед порождением потомка был создан канал, файловые дескрипторы для доступа к каналу будут унаследованы и сыном. В итоге обоим процессам оказываются доступны дескрипторы, связанные с каналом, и они могут использовать канал для обмена данными (см. Рис. 16 и Пример 17).

 

Рис. 16 Пример обмена данными между процессами через канал.

 Схема взаимодействия процессов с использованием канала.

#include <sys/types.h>

#include <unistd.h>

 

int main(int argc, char **argv)

{

int fd[2];

pipe(fd);

if (fork())

{/*процесс-родитель*/

close(fd[0]); /* закрываем ненужный дескриптор */

write (fd[1], …);

close(fd[1]);

}

else

{/*процесс-потомок*/

close(fd[1]); /* закрываем ненужный дескриптор */

while(read (fd[0], …))

{

}

}

}

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

Как правило, канал используется как однонаправленное средство передачи данных, т.е. только один из двух взаимодействующих процессов осуществляет запись в него, а другой процесс осуществляет чтение[10], при этом каждый из процессов закрывает не используемый им дескриптор. Это особенно важно для неиспользуемого дескриптора записи в канал, так как именно при закрытии пишущей стороны канала в него помещается символ конца файла. Если, к примеру, в рассмотренном Пример 17 процесс-потомок не закроет свой дескриптор записи в канал, то при последующем чтении из канала, исчерпав все данные из него, он будет заблокирован, так как  записывающая сторона канала будет открыта, и следовательно, читающий процесс будет ожидать очередной порции данных.