| PIPE(2) | Руководство программиста Linux | 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 для получения различного поведения:
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, errno устанавливается в соответствующее значение, а pipefd не изменяется.
В Linux (и других системах) pipe() не изменяет pipefd при ошибке. Требование стандартизации этого поведения было добавлено в POSIX.1-2016. Системный вызов Linux pipe2() также не изменяет pipefd при ошибке.
Вызов 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)
| 2019-03-06 | Linux |