pipe(2)

NAZWA
pipe, pipe2 - tworzy potok

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <unistd.h>

int pipe(int pipefd[2]);

#define _GNU_SOURCE             /* Zob. feature_test_macros(7) */
#include <fcntl.h>              /* Definicja stałych O_* */
#include <unistd.h>

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

/* Na Alpha, IA-64, MIPS, SuperH i SPARC/SPARC64, pipe() ma poniższy
   prototyp; zob. WERSJE */

#include <unistd.h>

struct fd_pair {
long fd[2];
};
struct fd_pair pipe(void);

OPIS
pipe() tworzy potok, jednokierunkowy kanał danych, służący do komunikacji między procesami. Tablica pipefd służy do zwrócenia dwóch deskryptorów pliku odnoszących się do końców potoku. pipefd[0] odnosi się do końca do odczytu. pipefd[1] odnosi się do końca do zapisu. Dane zapisywane do końca do zapisu potoku są buforowane przez jądro, do momentu ich odczytania z końca do odczytu potoku. Więcej szczegółów opisano w podręczniku pipe(7).

Jeśli flags ma wartość 0, to pipe2() jest równoważne pipe(). We flags można określić sumę bitową (OR) poniższych wartości, aby uzyskać odmienne zachowanie:

O_CLOEXEC
    Ustawia znacznik zamknij-przy-wykonaniu (close-on-exec; FD_CLOEXEC) na dwóch nowych deskryptorach pliku. Powody, dla których może być to przydatne, wskazano w opisie tego samego znacznika w podręczniku open(2).

O_DIRECT (od Linuksa 3.4)
    Tworzy potok, który przeprowadza wejście/wyjście w trybie „pakietowym”. Każdy zapis (write(2)) do potoku jest traktowany jako oddzielny pakiet, a odczyt (read(2)) z potoku odczyta jednocześnie pojedynczy pakiet. Proszę zauważyć, że:

    •   Zapis więcej niż PIPE_BUF bajtów (zob. pipe(7)) zostanie podzielony na kilka pakietów. Stała PIPE_BUF jest zdefiniowana w <limits.h>.

    •   Jeśli odczyt (read(2)) określi rozmiar bufora mniejszy niż następny pakiet, to odczytywana jest żądana liczba bajtów, a dodatkowe bajty pakietu są odrzucane. Podanie rozmiar bufora w wielkości PIPE_BUF wystarczy do odczytu nawet największych możliwych pakietów (zob. poprzedni punkt).

    •   Pakiety zerowej długości nie są obsługiwane (odczyt — read(2), określający rozmiar bufora na zero, będzie instrukcją pustą i zwróci 0).

    Starsze jądra, które nie obsługują tego znacznika, zasygnalizują ten fakt za pomocą błędu EINVAL.

    Od Linuksa 4.5, można zmienić ustawienie O_DIRECT deskryptora pliku potoku za pomocą fcntl(2).

O_NONBLOCK
    Ustawia znacznik stanu pliku O_NONBLOCK na opisach otwartego pliku (OFD), na które wskazują deskryptory nowych plików. Można w ten sposób oszczędzić sobie dodatkowych wywołań do fcntl(2), uzyskując ten sam rezultat.

O_NOTIFICATION_PIPE
    Od Linuksa 5.8, wokół potoków zbudowano ogólny mechanizm powiadomień, w którym jądro wplata komunikaty z powiadomieniami do potoków otwartych przez przestrzeń użytkownika. Właściciel potoku musi przekazać jądru, jakie źródło zdarzeń ma obserwować oraz jakie filtry mają być zastosowane, w celu wybrania zdarzeń podrzędnych, które mają być umieszczone w potoku.

WARTOŚĆ ZWRACANA
Po pomyślnym zakończeniu zwracane jest zero. W przypadku błędu zwracane jest -1 i ustawiane errno wskazując błąd, a pipefd pozostaje bez zmian.

W Linuksie (i innych systemach), pipe() nie modyfikuje pipefd w przypadku błędu. Wymaganie standaryzujące to zachowanie dodano w normie POSIX.1-2008 TC2. Typowo linuksowe wywołanie systemowe pipe2() również nie modyfikuje pipefd w przypadku błędu.

BŁĘDY

EFAULT
    pipefd jest nieprawidłowy.

EINVAL
    (pipe2()) Nieprawidłowa wartość we flags.

EMFILE
    Zostało osiągnięte ograniczenie na liczbę otwartych deskryptorów plików dla procesu.

ENFILE
    Zostało osiągnięte systemowe ograniczenie na całkowitą liczbę otwartych plików.

ENFILE
    Osiągnięto bezwzględny limit pamięci jaką można przydzielić potokom, a wywołujący nie jest uprzywilejowany, zob. pipe(7).

ENOPKG
    (pipe2()) We flags podano O_NOTIFICATION_PIPE, a obsługa powiadomień (CONFIG_WATCH_QUEUE) nie została wbudowana w jądro.

WERSJE
ABI Systemu V na niektórych architekturach umożliwia używanie więcej niż jednego rejestru, w celu zwracania kilku wartości; wiele architektur (w tym Alpha, IA-64, MIPS, SuperH i SPARC/SPARC64) (nad)używa tej funkcjonalności w celu implementacji wywołania systemowego pipe() w sposób funkcyjny: wywołanie nie przyjmuje żadnych argumentów i zwraca parę deskryptorów pliku w przypadku powodzenia. Funkcja opakowująca pipe() z glibc radzi sobie z tym w sposób przezroczysty. Podręcznik syscall(2) zawiera więcej informacji na temat rejestrów używanych do przechowywania drugiego deskryptora pliku.

STANDARDY
POSIX.1-2024.

HISTORIA

pipe()
    POSIX.1-2001.

pipe2()
    POSIX.1-2024. Linux 2.6.27, glibc 2.9.

PRZYKŁADY
Poniższy program tworzy potok, następnie tworzy nowy proces potomny za pomocą fork(2); potomek dziedziczy zduplikowany zestaw deskryptorów pliku, odnoszący się do tego samego potoku. Po wykonaniu fork(2), każdy proces zamyka deskryptory pliku, które nie są potrzebne potokowi (zob. pipe(7)). Rodzic zapisuje następnie łańcuch zawierający argumenty wiersza poleceń programu do potoku, a potomek odczytuje ten łańcuch z potoku bajt po bajcie i wypisuje go na standardowe wyjście.

  Kod źródłowy programu
    #include <err.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.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, "Użycie: %s <łańcuch>\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        if (pipe(pipefd) == -1)
            err(EXIT_FAILURE, "pipe");

        cpid = fork();
        if (cpid == -1)
            err(EXIT_FAILURE, "fork");

        if (cpid == 0) {    /* Potomek odczytuje z potoku */
            if (close(pipefd[1]) == -1)  /* Zamknięcie nieużywanego końca do zapisu */
                err(EXIT_FAILURE, "close");

            while (read(pipefd[0], &buf, 1) > 0) {
                if (write(STDOUT_FILENO, &buf, 1) != 1)
                    err(EXIT_FAILURE, "write");
            }

            if (write(STDOUT_FILENO, "\n", 1) != 1)
                err(EXIT_FAILURE, "write");
            if (close(pipefd[0]) == -1)
                err(EXIT_FAILURE, "close");
            _exit(EXIT_SUCCESS);

        } else {            /* Rodzic zapisuje argv[1] do potoku */
            if (close(pipefd[0]) == -1)  /* Zamkn. nieuż. końca do odczytu */
                err(EXIT_FAILURE, "close");
            if (write(pipefd[1], argv[1], strlen(argv[1])) != strlen(argv[1]))
                err(EXIT_FAILURE, "write");
            if (close(pipefd[1]) == -1)  /* Czytający zobaczy EOF */
                err(EXIT_FAILURE, "close");
            if (wait(NULL) == -1)        /* Czekanie na potomka */
                err(EXIT_FAILURE, "wait");
            exit(EXIT_SUCCESS);
        }
    }

ZOBACZ TAKŻE
fork(2), read(2), socketpair(2), splice(2), tee(2), vmsplice(2), write(2), popen(3), pipe(7)

TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: Przemek Borys <pborys@dione.ids.pl>, Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl> i Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 (https://www.gnu.org/licenses/gpl-3.0.html) lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.