dup(2)

NAZWA
dup, dup2, dup3 - duplikuje deskryptor pliku

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <unistd.h>

int dup(int oldfd);
int dup2(int oldfd, int newfd);

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

int dup3(int oldfd, int newfd, int flags);

OPIS
Wywołanie systemowe dup() przydziela nowy deskryptor pliku odnoszący się do tego samego opisu otwartego pliku (OFD), jak deskryptor oldfd (wyjaśnienie opisów otwartych plików znajduje się w podręczniku open(2)). Gwarantuje się, że nowy numer deskryptora pliku będzie najniższym numerem deskryptora pliku, który nie był używany w trakcie procesu wywoływania.

Po pomyślnym zakończeniu, stary i nowy deskryptor mogą być używane zamiennie. Oba deskryptory odnoszą się do tego samego opisu otwartego pliku, zatem współdzielą one przesunięcie pliku i znaczniki statusu pliku np. jeśli przesunięcie pliku zmieni się w wyniku użyciu lseek(2) na jednym z deskryptorów pliku, zmieni się ono także dla drugiego deskryptora pliku.

Oba deskryptory nie dzielą znaczników deskryptora pliku (znacznika zamknij-przy-wykonaniu). Znacznik zamknij-przy-wykonaniu (FD_CLOEXEC; zob. fcntl(2)) dla duplikatu deskryptora jest wyłączony.

  dup2()
Wywołanie systemowe dup2() wykonuje takie samo zadanie jak dup(), lecz zamiast używać najniższego numeru nieużywanego deskryptora pliku, używa numeru deskryptora pliku podanego w newfd. Innymi słowy, deskryptor pliku newfd jest dostosowywany tak, aby wskazywał teraz na ten sam opis otwartego pliku (ODF) jak oldfd.

Jeśli deskryptor pliku newfd był uprzednio otwarty, jest zamykany przed ponownym użyciem; zamknięcie jest przeprowadzane po cichu (tj. ewentualne błędy przy zamknięciu nie są zgłaszane przez dup2()).

Kroki zamykania i ponownego użycia deskryptora pliku newfd są wykonywane niepodzielnie. Jest to istotne, ponieważ próba zaimplementowania równoważnej funkcjonalności za pomocą close(2) i dup() prowadziłaby do hazardu, gdzie newfd mógłby być użyty ponownie pomiędzy oboma krokami. Mogłoby się tak zdarzyć, gdyby główny program został przerwany procedurą obsługi sygnału przydzielającego deskryptor plików lub gdyby równoległe wątki przydzielały deskryptor plików.

Proszę zauważyć, co następuje:

•   Jeśli oldfd nie jest prawidłowym deskryptorem pliku, to wywołanie zawiedzie, a newfd nie jest zamykane.

•   Jeśli oldfd jest prawidłowym deskryptorem pliku, a newfd ma tę samą wartość co oldfd, to dup2() niczego nie dokona i zwróci newfd.

  dup3()
dup3() działa jak dup2(), tyle że:

•   Wywołujący może wymusić, aby znacznik zamknięcia-przy-wykonaniu był ustawiony dla nowego deskryptora pliku podając O_CLOEXEC w flags. Proszę zapoznać się z opisem tego samego znacznika w open(2), aby przekonać się, dlaczego może być to użyteczne.

•   Jeśli oldfd równa się newfd, to dup3() zawodzi z błędem EINVAL.

WARTOŚĆ ZWRACANA
W przypadku powodzenia, te wywołania zwracają nowy deskryptor pliku. W razie wystąpienia błędu zwracane jest -1 i ustawiane jest errno wskazując błąd.

BŁĘDY

EBADF
    oldfd nie jest otwartym deskryptorem pliku.

EBADF
    newfd jest poza dozwolonym przedziałem dla deskryptorów pliku (zob. opis RLIMIT_NOFILE w getrlimit(2)).

EBUSY
    (tylko Linux) Błąd może być zwrócony przez dup2() lub dup3() w razie wystąpienia wyścigu z open(2) i dup().

EINTR
    Wywołanie dup2() lub dup3() przerwano sygnałem; zob. signal(7).

EINVAL
    (dup3()) flags zawiera nieprawidłową wartość.

EINVAL
    (dup3()) oldfd było równe newfd.

EMFILE
    Zostało osiągnięte ograniczenie na liczbę otwartych deskryptorów plików dla procesu (zob. opis RLIMIT_NOFILE w getrlimit(2)).

ENOMEM
    Brak pamięci jądra.

STANDARDY
POSIX.1-2024.

HISTORIA

dup()
dup2()
    4.3BSD, SVr4, POSIX.1-1988.

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

UWAGI
Błąd zwracany przez dup2() jest inny niż zwracany przez fcntl(..., F_DUPFD, ...) gdy newfd jest poza zakresem. W niektórych systemach dup2() zwraca też czasem EINVAL jako F_DUPFD.

Jeśli newfd był otwarty, wszelkie błędy, które mogłyby zostać zgłoszone w chwili wykonania close(2) zostaną utracone. Jeśli jest to istotne, to – o ile program jest jednowątkowy i nie przydziela deskryptorów pliku w procedurach obsługi sygnału – prawidłowym podejściem jest nie zamykanie newfd przez wywołanie dup2(), ze względu na sytuację hazardu opisaną powyżej. Zamiast tego, można użyć kodu podobnego do poniższego:

    /* Pozyskanie duplikatu 'newfd', którego można
       następnie użyć do sprawdzenia błędów close(); błąd EBADF
       oznacza, że 'newfd' nie był otwarty.  */

    tmpfd = dup(newfd);
    if (tmpfd == -1 && errno != EBADF) {
        /* Obsługa nieoczekiwanego błędu dup(). */
    }

    /* Niepodzielne zduplikowanie 'oldfd' w 'newfd'.  */

    if (dup2(oldfd, newfd) == -1) {
        /* Obsługa błędu dup2().  */
    }

    /* Teraz sprawdzenie błędów close() pliku, do którego
       'newfd' odnosił się pierwotnie.  */

    if (tmpfd != -1) {
        if (close(tmpfd) == -1) {
            /* Obsługa błędów z close.  */
        }
    }

ZOBACZ TAKŻE
close(2), fcntl(2), open(2), pidfd_getfd(2)

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.