dup, dup2 - dupliziert einen Datei-Deskriptor
Standard-C-Bibliothek (
libc,
-lc)
#include <unistd.h>
int dup(int altdd);
int dup2(int altdd, int neudd);
#define _GNU_SOURCE /* siehe feature_test_macros(7) */
#include <fcntl.h> /* Definition der O_*-Konstanten */
#include <unistd.h>
int dup3(int altdd, int neudd, int schalter);
Der Systemaufruf
dup() reserviert einen neuen Dateideskriptor, der sich
auf die gleiche offene Dateideskription wie der Deskriptor
altdd
bezieht. (Für eine Beschreibung von offenen Dateideskriptionen, siehe
open(2).) Die neue Dateideskriptornummer ist garantiert der
Dateideskriptor mit der niedrigsten Nummer, die in dem aufrufenden Prozess
verfügbar war.
Nach der erfolgreichen Rückkehr können die alten und neuen
Datei-Deskriptoren synonym benutzt werden. Da die zwei Dateideskriptoren sich
auf die gleichen offenen Dateideskriptionen beziehen, teilen sie sich dadurch
Dateiversatz (file offset) und Dateistatusschalter. Falls der Dateiversatz zum
Beispiel durch
lseek(2) auf einem der Dateideskriptoren geändert
wurde, wird der Versatz auch für den anderen Dateideskriptor
verändert.
Die beiden Dateideskriptoren teilen sich keine Datei-Deskriptor-Schalter (den
Schalter »close-on-exec«). Der Schalter
»close-on-exec« (
FD_CLOEXEC; siehe
fcntl(2))
für das Duplikat ist aus.
Der Systemaufruf
dup2() führt dieselben Aufgaben wie
dup()
durch, verwendet jedoch statt des kleinsten nicht benutzten Dateideskriptors
die in
neudd angegebene Zahl. Mit anderen Worten, der Dateideskriptor
neudd wird angepasst, so dass er sich jetzt auf die gleiche offene
Dateideskription wie
altdd bezieht.
Falls der Dateideskriptor
neudd vorher offen war, wird er vor der
erneuten Benutzung geschlossen; das Schließen erfolgt stillschweigend
(d.h. es werden mögliche Fehler während des Schließens
nicht durch
dup2() gemeldet).
Die Schritte zum Schließen und erneuten Verwenden des Dateideskriptors
neudd werden
atomar (als logische Einheit) durchgeführt.
Dies ist wichtig, da der Versuch gleichwertige Funktionalität mittels
close(2) und
dup()zu implementieren, Gegenstand von Race
Conditions sein könnte, bei denen
neudd zwischen zwei Schritten
erneut benutzt wird. Ein derartiges erneutes Verwenden kann vorkommen, da das
Hauptprogramm durch ein Signalverarbeitungsprogramm unterbrochen wird, der
einen Dateideskriptor reserviert oder weil ein paralleler Thread einen
Dateideskriptor reserviert.
Beachten Sie die folgenden Punkte:
- •
- Falls altdd kein gültiger Datei-Deskriptor
ist, schlägt der Aufruf fehl und neudd wird nicht
geschlossen.
- •
- Falls altdd ein gültiger Datei-Deskriptor ist
und neudd den gleichen Wert wie altdd hat, dann tut
dup2() nichts und gibt neudd zurück.
dup3() entspricht
dup2(), außer dass:
- •
- Der Aufrufende kann erzwingen, dass der Schalter
»close-on-exec« für den neuen Datei-Deskriptor durch
Angabe von O_CLOEXEC in schalter gesetzt wird. Lesen Sie die
Beschreibung des gleichnamigen Schalters in open(2), um zu
erfahren, warum dies nützlich sein könnte.
- •
- Falls altdd neudd entspricht, schlägt
dup3() mit dem Fehler EINVAL fehl.
Bei Erfolg geben diese Systemaufrufe den neuen Dateideskriptor zurück. Im
Fehlerfall wird -1 zurückgegeben und
errno gesetzt, um den
Fehler anzuzeigen.
- EBADF
-
altdd ist kein Deskriptor für eine
geöffnete Datei.
- EBADF
-
neudd liegt außerhalb des erlaubten Bereichs
für Datei-Deskriptoren (siehe die Erläuterung von
RLIMIT_NOFILE in getrlimit(2)).
- EBUSY
- (nur Linux) Dies könnte von dup2() oder
dup3() während einer Gleichzeitigkeitsbedingung mit
open(2) und dup() zurückgegeben werden.
- EINTR
- Der Aufruf von dup2() oder dup3() wurde von
einem Signal unterbrochen; lesen Sie signal(7).
- EINVAL
- (dup3()) schalter enthalten einen
ungültigen Wert.
- EINVAL
- (dup3()) altdd entsprach neudd.
- EMFILE
- Die Beschränkung der Anzahl offener
Datei-Deskriptoren pro Prozess wurde erreicht (siehe die
Erläuterung von RLIMIT_NOFILE in getrlimit(2)).
dup3() wurde in Linux 2.6.27 hinzugefügt;
Glibc-Unterstützung ist seit Glibc 2.9 verfügbar.
dup(),
dup2(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
dup3() ist Linux-spezifisch.
Der von
dup2 zurückgegebene Fehler unterscheidet sich von dem, der
von
fcntl(…,
F_DUPFD,…
)
zurückgegeben wird, wenn
neudd außerhalb des Bereiches
ist. Weiterhin gibt
dup2 auf einigen Systemen
EINVAL wie
F_DUPFD zurück.
Falls
neudd geöffnet war, sind alle Fehler verlorengegangen, die
in dieser Zeit an
close(2) gemeldet worden wären. Falls dies von
Bedeutung ist, ist die korrekte Herangehensweise, – sofern das Programm
nicht in einem einzigen Thread läuft und keine Dateideskriptoren in
Signalverarbeitungsprogrammen reserviert –,
neudd vor dem Aufruf
von
dup2() wegen der oben beschriebenen Race Conditions
nicht zu
schließen. Stattdessen kann Code wie der folgende verwendet werden:
/* Erhält ein Duplikat von »neudd«, das nachfolgend benutzt
werden kann, um auf Fehler von close() zu prüfen. Ein
EBADF-Fehler bedeutet, dass »neudd« nicht geöffnet war. */
tmpfd = dup(neudd);
if (tmpfd == -1 && errno != EBADF) {
/* behandelt unerwartete dup()-Fehler */
}
/* »altdd« atomar auf »neudd« duplizieren */
if (dup2(altdd, neudd) == -1) {
/* dup2()-Fehler behandeln */
}
/* Nun wird auf close()-Fehler für die Datei, auf die sich
»neudd« ursprünglich bezog, geprüft. */
if (tmpfd != -1) {
if (close(tmpfd) == -1) {
/* close-Fehler behandeln */
}
}
close(2),
fcntl(2),
open(2),
pidfd_getfd(2)
Die deutsche Übersetzung dieser Handbuchseite wurde von Aldo Valente
<
[email protected]>, Chris Leick <
[email protected]> und
Helge Kreutzmann <
[email protected]> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die
GNU
General Public License Version 3 oder neuer bezüglich der
Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken
Sie bitte eine E-Mail an die
Mailingliste
der Übersetzer