Linux Man на русском

  User    Syst    Libr    Device    Files    Other    Admin  



   pipe - создаёт канал

pipe(2) создаёт канал

Other Alias

pipe2


ОБЗОР

#include <unistd.h>


int pipe(int pipefd[2]);

#define _GNU_SOURCE /* Смотрите feature_test_macros(7) */
#include <fcntl.h> /* Определение констант O_* */
#include <unistd.h>

int pipe2(int pipefd[2], int flags);


ОПИСАНИЕ

pipe() создаёт однонаправленный канал данных, который можно использовать для взаимодействия между процессами. Массив pipefd используется для возврата двух файловых описателей, указывающих на концы канала. pipefd[0] указывает на конец канала для чтения. pipefd[1] указывает на конец канала для записи. Данные, записанные в конец канала, буферизируются ядром до тех пор, пока не будут прочитаны из конца канала для чтения. Подробней см. pipe(7).

Если flags равно 0, то pipe2() выполняет то же что и pipe(). Следующие значения могут быть побитово сложены в flags для получения различного поведения:

O_CLOEXEC Устанавливает флаг close-on-exec (FD_CLOEXEC) для двух новых открытых файловых дескрипторов. Смотрите описание того же флага в open(2) для того, чтобы узнать как это может пригодиться.

O_DIRECT (начиная с Linux 3.4) Создаёт канал, в котором ввод-вывод выполняется в «пакетном» режиме. Каждый write(2) в канал рассматривается как отдельный пакет, а read(2) из канала читает один пакет за раз. Заметим следующее:

  • Запись более PIPE_BUF байт (смотрите pipe(7)) будет разделена на несколько пакетов. Константа PIPE_BUF определена в <limits.h>.
  • Если в read(2) указан размер буфера меньше чем следующий пакет, то читается запрашиваемое количество байт, а лишние байты пакета отбрасываются. Указание PIPE_BUF в качестве размера буфера будет достаточно для чтения самых больших пакетов (смотрите предыдущее примечание).
  • Пакеты нулевой длины не поддерживаются (вызов read(2) с нулевым размером буфера ничего не делает и возвращает 0).
    Старые ядра, которые не поддерживают этот флаг, возвращают ошибку EINVAL.

    O_NONBLOCK Устанавливает флаг состояния файла O_NONBLOCK для двух новых открытых файловых дескрипторов. Использование данного флага заменяет дополнительные вызовы fcntl(2) для достижения того же результата.


    ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

    При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.


    ОШИБКИ

    EFAULT pipefd задан некорректно.

    EINVAL (pipe2()) Некорректное значение flags.

    EMFILE Было достигнуто ограничение по количеству открытых файловых дескрипторов на процесс.

    ENFILE Достигнуто максимальное количество открытых файлов в системе.

    ВЕРСИИ

    Вызов pipe2() был добавлен в Linux начиная с версии 2.6.27; поддержка в glibc появилась начиная с версии 2.9.


    СООТВЕТСТВИЕ СТАНДАРТАМ

    pipe(): POSIX.1-2001, POSIX.1-2008.

    Вызов pipe2() есть только в Linux.


    ПРИМЕР

    Следующая программа создаёт канал, и затем выполняет fork(2) для создания потомка; потомок наследует скопированный набор файловых дескрипторов, которые указывают на тот же канал. После fork(2) каждый процесс закрывает файловые дескрипторы, которые ненужны каналу (см. pipe(7)). Затем родитель записывает строку, переданную в качестве аргумента командной строки, в канал, а потомок читает эту строку из канала по байту за раз, и выводит её на стандартный вывод.

    Исходный код программы

    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    int
    main(int argc, char *argv[])
    {
        int pipefd[2];
        pid_t cpid;
        char buf;
        if (argc != 2) {
            fprintf(stderr, "Использование: %s <string>\n", argv[0]);
            exit(EXIT_FAILURE);
        }
        if (pipe(pipefd) == -1) {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
        cpid = fork();
        if (cpid == -1) {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        if (cpid == 0) {    /* Потомок читает из канала */
            close(pipefd[1]);          /* Закрывает неиспользуемый конец для записи */
            while (read(pipefd[0], &buf, 1) > 0)
                write(STDOUT_FILENO, &buf, 1);
            write(STDOUT_FILENO, "\n", 1);
            close(pipefd[0]);
            _exit(EXIT_SUCCESS);
        } else {            /* Родитель пишет значение argv[1] в канал */
            close(pipefd[0]);          /* Закрывает неиспользуемый конец для чтения */
            write(pipefd[1], argv[1], strlen(argv[1]));
            close(pipefd[1]);          /* Читатель видит EOF */
            wait(NULL);                /* Ожидание потомка */
            exit(EXIT_SUCCESS);
        }
    }