dup(2)

NUME
dup, dup2, dup3 - duplică un descriptor de fișier

BIBLIOTECA
Biblioteca C standard (libc, -lc)

SINOPSIS
#include <unistd.h>

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

#define _GNU_SOURCE             /* Consultați feature_test_macros(7) */
#include <fcntl.h>              /* Definirea constantelor O_* */
#include <unistd.h>

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

DESCRIERE
Apelul de sistem dup() alocă un nou descriptor de fișier care se referă la aceeași descriere de fișier deschis ca descriptorul oldfd (pentru o explicație a descrierilor de fișiere deschise, consultați open(2)). Numărul noului descriptor de fișier este garantat a fi cel mai mic descriptor de fișier care nu a fost utilizat în procesul apelant.

După o returnare reușită, descriptorii de fișier vechi și nou pot fi utilizați în mod interschimbabil. Deoarece cei doi descriptori de fișier se referă la aceeași descriere de fișier deschis, aceștia au în comun indicatorii de poziție și de stare a fișierului; de exemplu, dacă poziția fișierului este modificată prin utilizarea lseek(2) pe unul dintre descriptorii de fișier, poziția este modificată și pentru celălalt descriptor de fișier.

Cei doi descriptori de fișier nu au în comun fanioanele descriptorului de fișier (fanionul close-on-exec). Fanionul close-on-exec (FD_CLOEXEC; a se vedea fcntl(2)) pentru descriptorul duplicat este dezactivat.

  dup2()
Apelul de sistem dup2() îndeplinește aceeași sarcină ca și dup(), dar în loc să utilizeze descriptorul de fișier neutilizat cu cel mai mic număr, utilizează numărul descriptorului de fișier specificat în newfd. Cu alte cuvinte, descriptorul de fișier newfd este ajustat astfel încât să se refere acum la aceeași descriere de fișier deschis ca oldfd.

În cazul în care descriptorul de fișier newfd a fost deschis anterior, acesta este închis înainte de a fi reutilizat; închiderea este efectuată în mod silențios (de exemplu, eventualele erori din timpul închiderii nu sunt raportate de dup2()).

Etapele de închidere și reutilizare a descriptorului de fișier newfd sunt efectuate atomic. Acest lucru este important, deoarece încercarea de a pune în aplicare o funcționalitate echivalentă folosind close(2) și dup() ar fi supusă unor condiții de cursă, prin care newfd ar putea fi reutilizat între cele două etape. O astfel de reutilizare ar putea avea loc deoarece programul principal este întrerupt de un gestionar de semnal care alocă un descriptor de fișier sau deoarece un fir paralel alocă un descriptor de fișier.

Rețineți următoarele puncte:

•   Dacă oldfd nu este un descriptor de fișier valid, apelul eșuează, iar newfd nu este închis.

•   Dacă oldfd este un descriptor de fișier valid, iar newfd are aceeași valoare ca oldfd, atunci dup2() nu face nimic și returnează newfd.

  dup3()
dup3() este la fel ca dup2(), cu excepția faptului că:

•   Apelantul poate forța activarea indicatorului close-on-exec pentru noul descriptor de fișier prin specificarea O_CLOEXEC în flags. A se vedea descrierea aceluiași fanion în open(2) pentru motivele pentru care acest lucru poate fi util.

•   Dacă oldfd este egal cu newfd, atunci dup3() eșuează cu eroarea EINVAL.

VALOAREA RETURNATĂ
În caz de succes, aceste apeluri de sistem returnează noul descriptor de fișier. În caz de eroare, este returnat -1, iar errno este configurată pentru a indica eroarea.

ERORI-IEȘIRE

EBADF
    oldfd nu este un descriptor de fișier deschis.

EBADF
    newfd este în afara intervalului permis pentru descriptorii de fișiere (a se vedea discuția despre RLIMIT_NOFILE în getrlimit(2)).

EBUSY
    (Numai Linux) Aceasta poate fi returnată de dup2() sau dup3() în timpul unei condiții de cursă cu open(2) și dup().

EINTR
    Apelul dup2() sau dup3() a fost întrerupt de un semnal; consultați signal(7).

EINVAL
    (dup3()) flags conține o valoare nevalidă.

EINVAL
    (dup3()) oldfd a fost egal cu newfd.

EMFILE
    A fost atinsă limita per-proces privind numărul de descriptoare de fișiere deschise (a se vedea discuția despre RLIMIT_NOFILE în getrlimit(2)).

ENOMEM
    Nu a fost disponibilă suficientă memorie pentru nucleu.

STANDARDE
POSIX.1-2024.

ISTORIC

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

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

NOTE
Eroarea returnată de dup2() este diferită de cea returnată de fcntl(..., F_DUPFD, ...) atunci când newfd iese din interval. Pe unele sisteme, dup2() returnează uneori și EINVAL ca F_DUPFD.

Dacă newfd a fost deschis, orice erori care ar fi fost raportate la momentul close(2) sunt pierdute. Dacă acest lucru vă îngrijorează, atunci [em]cu excepția cazului în care programul este cu un singur fir și nu alocă descriptori de fișier în gestionarii de semnal [em]abordarea corectă este să nu închideți newfd înainte de a apela dup2(), din cauza condiției de cursă descrisă mai sus. În schimb, ar putea fi utilizat un cod asemănător cu următorul:

    /* Obține un duplicat al 'newfd' care poate fi utilizat
       ulterior pentru a verifica erorile close(); o eroare EBADF
       înseamnă că 'newfd' nu a fost deschis. */

    tmpfd = dup(newfd);
    if (tmpfd == -1 && errno != EBADF) {
        /* Gestionează eroarea neașteptată dup(). */
    }

    /* Duplicarea atomică a 'oldfd' pe 'newfd'. */

    if (dup2(oldfd, newfd) == -1) {
        /* Gestionează eroarea dup2(). */
    }

    /* Acum verifică dacă există erori close() în fișierul menționat
       inițial de 'newfd'. */

    if (tmpfd != -1) {
        if (close(tmpfd) == -1) {
            /* Gestionează erorile de la închidere. */
        }
    }

CONSULTAȚI ȘI
close(2), fcntl(2), open(2), pidfd_getfd(2)

TRADUCERE
Traducerea în limba română a acestui manual a fost făcută de Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>

Această traducere este documentație gratuită; citiți Licența publică generală GNU Versiunea 3 (https://www.gnu.org/licenses/gpl-3.0.html) sau o versiune ulterioară cu privire la condiții privind drepturile de autor. NU se asumă NICIO RESPONSABILITATE.

Dacă găsiți erori în traducerea acestui manual, vă rugăm să trimiteți un e-mail la translation-team-ro@lists.sourceforge.net.