pipe, pipe2 - создаёт
канал
Standard C library (
libc,
-lc)
#include <unistd.h>
int pipe(int pipefd[2]);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Definition of O_* constants */
#include <unistd.h>
int pipe2(int pipefd[2], int flags);
/* On Alpha, IA-64, MIPS, SuperH, and SPARC/SPARC64, pipe() has the
following prototype; see NOTES */
#include <unistd.h>
struct fd_pair {
long fd[2];
};
struct fd_pair pipe(void);
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)
для
достижения
того же
результата.
- O_NOTIFICATION_PIPE
- Since Linux 5.8, general notification mechanism is built on
the top of the pipe where kernel splices notification messages into pipes
opened by user space. The owner of the pipe has to tell the kernel which
sources of events to watch and filters can also be applied to select which
subevents should be placed into the pipe.
On success, zero is returned. On error, -1 is returned,
errno is set to
indicate the error, and
pipefd is left unchanged.
В Linux (и других
системах)
pipe() не
изменяет
pipefd
при ошибке.
Требование
стандартизации
этого
поведения
было
добавлено
в POSIX.1-2008 TC2.
Системный
вызов Linux
pipe2()
также не
изменяет
pipefd
при ошибке.
- EFAULT
-
pipefd задан
некорректно.
- EINVAL
- (pipe2())
Некорректное
значение
flags.
- EMFILE
- Было
достигнуто
ограничение
по
количеству
открытых
файловых
дескрипторов
на
процесс.
- ENFILE
- Достигнуто
максимальное
количество
открытых
файлов в
системе.
- ENFILE
- Достигнуто
жёсткое
пользовательское
ограничение
на
выделение
памяти для
каналов и
вызывающий
не имеет
дополнительных
прав;
смотрите
pipe(7).
- ENOPKG
- (pipe2()) O_NOTIFICATION_PIPE was passed in
flags and support for notifications ( CONFIG_WATCH_QUEUE) is
not compiled into the kernel.
pipe2() was added in Linux 2.6.27; glibc support is available starting
with glibc 2.9.
pipe(): POSIX.1-2001, POSIX.1-2008.
Вызов
pipe2()
есть
только в Linux.
System V ABI на
некоторых
архитектурах
позволяет
использовать
более
одного
регистра
для
возврата
нескольких
значений; в
нескольких
архитектурах
(Alpha, IA-64, MIPS, SuperH и SPARC/SPARC64)
использована
эта
возможность
для
реализации
системного
вызова
pipe()
подобно
функциям:
вызов не
использует
параметры
и при
успешном
выполнении
возвращает
пару
файловых
дескрипторов
как
результат.
Обёрточная
функция glibc
pipe()
учитывает
это.
Описание
регистров
хранения
второго
файлового
дескриптора
смотрите в
syscall(2).
Следующая
программа
создаёт
канал, и
затем
выполняет
fork(2) для
создания
потомка;
потомок
наследует
скопированный
набор
файловых
дескрипторов,
которые
указывают
на тот же
канал.
После
fork(2)
каждый
процесс
закрывает
файловые
дескрипторы,
которые
ненужны
каналу (см.
pipe(7)). Затем
родитель
записывает
строку,
переданную
в качестве
аргумента
командной
строки, в
канал, а
потомок
читает эту
строку из
канала по
байту за
раз, и
выводит её
на
стандартный
вывод.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
int pipefd[2];
char buf;
pid_t cpid;
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)
Русский
перевод
этой
страницы
руководства
был сделан
Alexey, Azamat Hackimov <
[email protected]>, kogamatranslator49
<
[email protected]>, Kogan, Max Is <
[email protected]>, Yuri
Kozlov <
[email protected]> и Иван
Павлов <
[email protected]>
Этот
перевод
является
бесплатной
документацией;
прочитайте
Стандартную
общественную
лицензию GNU
версии 3
или более
позднюю,
чтобы
узнать об
условиях
авторского
права. Мы не
несем
НИКАКОЙ
ОТВЕТСТВЕННОСТИ.
Если вы
обнаружите
ошибки в
переводе
этой
страницы
руководства,
пожалуйста,
отправьте
электронное
письмо на
[email protected]