dup2 / dup – warum sollte ich einen Dateideskriptor duplizieren müssen?
Lesezeit: 6 Minuten
Jan
Ich versuche, die Verwendung von zu verstehen dup2 und dup.
Aus der Manpage:
DESCRIPTION
dup and dup2 create a copy of the file descriptor oldfd.
After successful return of dup or dup2, the old and new descriptors may
be used interchangeably. They share locks, file position pointers and
flags; for example, if the file position is modified by using lseek on
one of the descriptors, the position is also changed for the other.
The two descriptors do not share the close-on-exec flag, however.
dup uses the lowest-numbered unused descriptor for the new descriptor.
dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.
RETURN VALUE
dup and dup2 return the new descriptor, or -1 if an error occurred
(in which case, errno is set appropriately).
Wozu brauche ich diesen Systemaufruf? Was bringt es, den Dateideskriptor zu duplizieren?
Wenn ich den Dateideskriptor habe, warum sollte ich eine Kopie davon machen wollen?
Ich würde mich freuen, wenn Sie erklären und mir ein Beispiel geben könnten, wo dup2 / dup wird gebraucht.
Vielen Dank
Wie würden Sie die Piping-Funktionalität von Shells ohne implementieren dup oder dup2 ? Sie müssen anrufen pipe(2) und dann einen der Dateideskriptoren zu haben dup-ed zu zB STDIN_FILENO
– Basile Starynkevitch
24. Juli 2012 um 23:52 Uhr
Mögliches Duplikat von praktischen Beispielen verwenden Sie dup oder dup2
– DrTyrsa
20. Januar 2017 um 10:27 Uhr
Tiefer Gedanke
Der Systemaufruf dup dupliziert einen vorhandenen Dateideskriptor und gibt einen neuen zurück, der auf dasselbe zugrunde liegende E/A-Objekt verweist.
Dup ermöglicht es Shells, Befehle wie diesen zu implementieren:
ls existing-file non-existing-file > tmp1 2>&1
Das 2>&1 weist die Shell an, dem Befehl einen Dateideskriptor 2 zu geben, der ein Duplikat von Deskriptor 1 ist (dh stderr & stdout zeigen auf dasselbe fd).
Nun die Fehlermeldung zum Aufrufen ls an nicht vorhandene Datei und die korrekte Ausgabe von ls an vorhandene Datei zeige dich ein tmp1 Datei.
Der folgende Beispielcode führt das Programm wc mit Standardeingabe aus, die mit dem Leseende einer Pipe verbunden ist.
int p[2];
char *argv[2];
argv[0] = "wc";
argv[1] = 0;
pipe(p);
if(fork() == 0) {
close(STDIN); //CHILD CLOSING stdin
dup(p[STDIN]); // copies the fd of read end of pipe into its fd i.e 0 (STDIN)
close(p[STDIN]);
close(p[STDOUT]);
exec("/bin/wc", argv);
} else {
write(p[STDOUT], "hello world\n", 12);
close(p[STDIN]);
close(p[STDOUT]);
}
Das Kind dupliziert das gelesene Ende auf den Dateideskriptor 0, schließt die Dateideskriptoren in p und führt wc aus. Wenn wc von seiner Standardeingabe liest, liest es von der Pipe.
So werden Pipes mit dup implementiert, nun, bei einer Verwendung von dup verwenden Sie jetzt pipe, um etwas anderes zu erstellen. Das ist das Schöne an Systemaufrufen. Sie erstellen eine Sache nach der anderen mit Tools, die bereits vorhanden sind. Diese Tools wurden wiederum mit erstellt etwas anderes usw. Am Ende sind Systemaufrufe die grundlegendsten Werkzeuge, die Sie im Kernel erhalten
Prost 🙂
Sodup ist für den anrufer hilfreich und nicht der ls selbst programmieren? Gibt es einen Vorteil zu haben dup Wird in Programmen wie ls selbst verwendet, wenn bereits Zugriff auf die Datei besteht? Hier zum Beispiel ls schreibt Fehler nach 2 Das ist fest codiert, also habe ich eine Möglichkeit, es als Verbraucher von zu überschreiben ls. Ich denke, das ist ein subtiler Punkt, nein?
– Nischant
28. März 2016 um 11:29 Uhr
Ihr Beispielprogramm scheint einen Fehler haben; du rufst an dup(p[STDIN]) aber dann das Ergebnis wegwerfen. Wollten Sie verwenden dup2(p[STDIN], 0)?
– Quuxplusone
8. August 2017 um 18:27 Uhr
@Quuxplusone dup gibt den “Deskriptor mit der niedrigsten Nummer, der derzeit nicht vom Prozess verwendet wird” zurück. Da fd 0 gerade geschlossen wurde, dup sollte 0 zurückgeben. dup2 ist explizit, welche fd verwendet werden soll, anstatt nur die niedrigste freie fd zu verwenden, also würde ich das bevorzugen.
– Wodin
28. Dezember 2017 um 5:14 Uhr
@Wodin: Ah, ich wette, Sie haben Recht mit dem, was OP gedacht hat. Habe ich aber auch Recht, dass “gerade geschlossen” relativ ist und der Code von OP beispielsweise bei gleichzeitigen Threads, die möglicherweise auch Dateien öffnen, beschädigt werden könnte?
– Quuxplusone
28. Dezember 2017 um 17:48 Uhr
@Wodin JFI: mit dup2 du würdest nicht anrufen close Vor.
– blauäugig
20. Februar 2020 um 15:44 Uhr
Ein weiterer Grund für das Duplizieren eines Dateideskriptors ist die Verwendung mit fdopen. fclose schließt den Dateideskriptor, an den übergeben wurde fdopenwenn Sie also nicht möchten, dass der ursprüngliche Dateideskriptor geschlossen wird, müssen Sie ihn mit duplizieren dup Erste.
fdopen() scheint keinen Dateideskriptor zu duplizieren, sondern nur einen Puffer im Benutzerbereich zu erstellen.
– Erich
5. Mai 2015 um 5:11 Uhr
Du hast meine Antwort falsch verstanden. Der Punkt ist, dass Sie es vielleicht wollen dup die fd, bevor Sie sie an übergeben fdopen seit fclose wird es schließen.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
5. Mai 2015 um 15:30 Uhr
@theferrit32: Wenn Sie a FILE handle, um über stdio-Schnittstellen auf eine bereits vorhandene offene Datei zuzugreifen, müssen Sie aufrufen fclose das aufzuheben FILE handhaben. Wenn Sie die zugrunde liegende geöffnete Datei weiter verwenden möchten oder wenn Ihre Softwarearchitektur so ist, dass der ursprüngliche “Eigentümer” -Code für den Dateideskriptor verwendet wird close es, die Tatsache, dass fclose schließt auch den zugrunde liegenden Dateideskriptor, an den Sie übergeben haben fdopen ist ein Problem. Sie können dieses Problem vermeiden, indem Sie verwenden dup um einen neuen Dateideskriptor für dieselbe geöffnete Datei zu erstellen, an die übergeben werden soll fdopenso dass fclose schließt das Original nicht.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
1. November 2018 um 2:33 Uhr
Der Punkt ist, dass fdopen() bewegt Eigentum der fd an die FILEstatt Kopieren es. Dessen sollten sich Nutzer bewusst sein. Verbraucher, die ein nutzbares Produkt behalten müssen fd zusätzlich zu behandeln FILE Objekt muss duplizieren fd. Das ist alles.
– Konrad Meyer
18. März 2020 um 18:16 Uhr
@ConradMeyer: Ja, das ist eine sehr gute Art, es auszudrücken, mit dem Hinweis, dass es keine Operation gibt, um “Eigentum zu verschieben” von der FILE sobald Sie den Besitz darauf übertragen.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
18. März 2020 um 18:50 Uhr
dup wird verwendet, um die Ausgabe eines Prozesses umleiten zu können.
Wenn Sie beispielsweise die Ausgabe eines Prozesses speichern möchten, duplizieren Sie die Ausgabe (fd = 1), leiten das duplizierte fd in eine Datei um, forken und führen den Prozess aus, und wenn der Prozess beendet ist, leiten Sie erneut um fd zur Ausgabe gespeichert.
Bitte beachten Sie einige Punkte im Zusammenhang mit dup/dup2
dup/dup2 – Technisch gesehen besteht der Zweck darin, einen Dateitabelleneintrag in a zu teilen einzelner Prozess durch verschiedene Griffe. (Wenn wir forken, wird der Deskriptor standardmäßig im untergeordneten Prozess dupliziert und der Dateitabelleneintrag wird ebenfalls geteilt).
Das bedeutet, dass wir mehr als einen Dateideskriptor haben können möglicherweise unterschiedliche Attribute für einen einzigen offenen Dateitabelleneintrag mit der Funktion dup/dup2.
(Obwohl derzeit nur das FD_CLOEXEC-Flag das einzige Attribut für einen Dateideskriptor zu sein scheint).
dup(fd) is equivalent to fcntl(fd, F_DUPFD, 0);
dup2(fildes, fildes2); is equivalent to
close(fildes2);
fcntl(fildes, F_DUPFD, fildes2);
Die Unterschiede sind (zuletzt) - Abgesehen von einigen errno-Werten zwischen dup2 und fcntl close gefolgt von fcntl kann es zu Race-Conditions kommen, da zwei Funktionsaufrufe beteiligt sind.
Wie würden Sie die Piping-Funktionalität von Shells ohne implementieren
dup
oderdup2
? Sie müssen anrufenpipe(2)
und dann einen der Dateideskriptoren zu habendup
-ed zu zBSTDIN_FILENO
– Basile Starynkevitch
24. Juli 2012 um 23:52 Uhr
Mögliches Duplikat von praktischen Beispielen verwenden Sie dup oder dup2
– DrTyrsa
20. Januar 2017 um 10:27 Uhr