PIPE(2)

ИМЯ
pipe, pipe2 - создаёт канал

ОБЗОР
#include <unistd.h>

/* На Alpha, IA-64, MIPS, SuperH и SPARC/SPARC64; смотрите ЗАМЕЧАНИЯ */
struct fd_pair {
long fd[2];
};
struct fd_pair pipe();

/* На остальных архитектурах */
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.

    Начиная с Linux 4.5, у файлового дескриптора канала возможно менять установку O_DIRECT с помощью fcntl(2).

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

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, errno устанавливается в соответствующее значение, а pipefd не изменяется.

В Linux (и других системах) pipe() не изменяет pipefd при ошибке. Требование стандартизации этого поведения было добавлено в POSIX.1-2016. Системный вызов Linux pipe2() также не изменяет pipefd при ошибке.

ОШИБКИ

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

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

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

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

ENFILE
    Достигнуто жёсткое пользовательское ограничение на выделение памяти для каналов и вызывающий не имеет дополнительных прав; смотрите pipe(7).

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

ЗАМЕЧАНИЯ
SystemV ABI на некоторых архитектурах позволяет использовать более одного регистра для возврата нескольких значений; в нескольких архитектурах (Alpha, IA-64, MIPS, SuperH и SPARC/SPARC64) использована эта возможность для реализации системного вызова pipe() подобно функциям: вызов не использует параметры и при успешном выполнении возвращает пару файловых дескрипторов как результат. Обёрточная функция glibc pipe() учитывает это. Описание регистров хранения второго файлового дескриптора смотрите в syscall(2).

СООТВЕТСТВИЕ СТАНДАРТАМ
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);
        }
    }

СМОТРИТЕ ТАКЖЕ
fork(2), read(2), socketpair(2), splice(2), tee(2), vmsplice(2), write(2), popen(3), pipe(7)