next up previous contents
Next: Функция popen(). Up: Трубы (pipes) Previous: Трубы (pipes)   Contents

Использование труб.

Труба является однонаправленным коммуникационным каналом между двумя процессами. Кроме поддержки коммуникации труба может использоваться для контроля информационного потока между двумя процессами. Это происходит потому, что труба может принимать только определенный объем данных (обычно 4 Кб). Если труба заполнена, процесс останавливается до тех пор, пока хотя бы один байт не будет прочитан из этой трубы и не появится свободное место, чтобы снова заполнять ее данными. С другой стороны, если труба пуста, то читающий процесс останавливается до тех пор, пока пишущий процесс не пошлет что-либо в эту трубу.

Труба владеет двумя дескрипторами файлов. Первый дескриптор служит для чтения, а второй для записи в трубу:

#include <unistd.h>

int pipe(int fd[2]);

Здесь fd[0] является дескриптором для чтения, а fd[1] - дескриптором для записи в трубу.

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

В приведенном ниже примере (рис. 9) процесс-родитель будет записывать данные в трубу. Таким образом, дескриптор чтения (fd[0]) родительского процесса закрывается. Дескриптор записи потомка так же закрывается. Потомок будет только читать данные из трубы.

#include <unistd.h>

#include <sys/wait.h>

#include <stdio.h>

#include <sys/types.h>

#include <fcntl.h>

#define USAGE printf("usage : %s данные\n",argv[0]);

#define MAX 4096

int main(int argc, char *argv[])

{

  int fd[2], fd1,i, n;

  pid_t pid;

  char buffer[MAX];

  FILE *dataptr;

  if(argc !=2)

    { USAGE; exit(0); }

  if((fd1=open(argv[1], O_RDONLY)) < 0)

     { perror("open : "); exit(0); }

   

  /*Устанавливаем трубу*/

  if(pipe(fd) < 0)

    { perror("pipe : "); exit(0); }

 

  /*Создаем новый процесс*/

  if((pid=fork()) < 0)

    { perror("pipe : "); exit(0); }

 

  else if(pid > 0) /*Это родитель*/

  {

    close(fd[0]); /*Закрываем чтение*/

    n=read(fd1, buffer, MAX);

    if((write(fd[1], buffer, n)) != n)

      { perror(" write : "); exit(0); }

    if((waitpid(pid, NULL, 0)) < 0)

       { perror("waitpid : "); exit(0); }

  }

 

  else /*Это потомок*/

  {

    close(fd[1]); /*Закрываем запись*/

    n=read(fd[0], buffer, MAX);

    if((write(STDOUT_FILENO, buffer, n)) != n)

      { perror(" write : "); exit(0); }

  }

  exit(0);

}

Рис. 9. Простое взаимодействие через трубы.



2003-12-09