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(). При этом процесс-потомок наследует от родителя оба открытых дескриптора файлов. После этого, закрыв ненужные дескрипторы, необходимо указать обоим процессам, кто куда пишет и кто что читает.

В приведенном ниже примере процесс-родитель записывает данные в трубу. В этом случае закрываются дескриптор чтения (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);

}



2004-06-22