dup2 / dup – warum sollte ich einen Dateideskriptor duplizieren müssen?

Lesezeit: 6 Minuten

Benutzeravatar von JAN
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

Benutzeravatar von Deepthought
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).

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

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.

Details können aus überprüft werden
http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html

Ein Anwendungsbeispiel

Ein interessantes Beispiel bei der Implementierung der Jobsteuerung in einer Shell, wo die Verwendung von dup/dup2 zu sehen ist … im folgenden Link

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

1420480cookie-checkdup2 / dup – warum sollte ich einen Dateideskriptor duplizieren müssen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy