ich weiß was dup
/ dup2
tut, aber ich habe keine Ahnung, wann es verwendet werden würde.
Irgendwelche praktischen Beispiele?
Vielen Dank.
pierrotlefou
ich weiß was dup
/ dup2
tut, aber ich habe keine Ahnung, wann es verwendet werden würde.
Irgendwelche praktischen Beispiele?
Vielen Dank.
Alfonso
Eine beispielhafte Verwendung wäre die E/A-Umleitung. Dazu verzweigen Sie einen untergeordneten Prozess und schließen die stdin- oder stdout-Dateideskriptoren (0 und 1) und führen dann ein dup() auf einem anderen Dateideskriptor Ihrer Wahl aus, der nun dem niedrigsten verfügbaren Dateideskriptor zugeordnet wird, der sich in diesem befindet Fall 0 oder 1.
Damit können Sie jetzt jeden untergeordneten Prozess ausführen, der Ihre Anwendung möglicherweise nicht kennt, und immer wenn der untergeordnete Prozess auf die Standardausgabe schreibt (oder von der Standardeingabe liest, was auch immer Sie konfiguriert haben), werden die Daten stattdessen in den bereitgestellten Dateideskriptor geschrieben.
Shells verwenden dies, um Befehle mit Pipes zu implementieren, z /bin/ls | more
indem Sie die stdout eines Prozesses mit der stdin des anderen verbinden.
@nshy: Sie können normal verwenden dup()
um stdout in einen anderen Dateideskriptor zu kopieren, bevor es umgeleitet wird. Auf diese Weise können Sie es später rückgängig machen. Wenn Sie verwendet haben dup2()
würden Sie riskieren, einen vorhandenen Deskriptor zu überschreiben.
– Kevin
12. Februar 2015 um 16:49 Uhr
@krusty: Siehe diese Antwort auf eine andere SO-Frage.
– Benutzer1071847
31. Dezember 2018 um 14:17 Uhr
ZijunLost
Das beste Szenario zum Verständnis von dup und dup2 ist die Umleitung.
Als erstes müssen wir wissen, dass das System 3 Standard-Datei-IDs (oder Variablen, die Ausgabe- oder Eingabequellen angeben) hat, die sich mit der Eingabe und Ausgabe befassen. Sie sind stdin
, stdout
, stderr
in ganzen Zahlen sind sie 0
,1
,2
. Die meisten Funktionen wie fprintf
oder cout
direkt ausgegeben werden stdout
.
Wenn wir die Ausgabe umleiten möchten, gibt es zum Beispiel eine Möglichkeit, fprintf
Funktion mehr Argumente angeben in
und out
.
Es gibt jedoch einen eleganteren Weg: Wir können die Standard-Datei-IDs überschreiben, damit sie auf die Datei verweisen, die wir die Ausgabe erhalten möchten. dup
und dup2
genau in dieser Situation funktionieren.
Beginnen wir jetzt mit einem einfachen Beispiel: Angenommen, wir möchten die Ausgabe von umleiten fprintf
in eine txt-Datei mit dem Namen “chinaisbetter.txt”. Zuerst müssen wir diese Datei öffnen
int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);
Dann wollen wir stdout
um auf “chinaisbetter.txt” mit der dup-Funktion zu zeigen:
dup2(fw,1);
Jetzt zeigt stdout(1) auf den Deskriptor von “chinaisbetter.txt”, obwohl es immer noch 1 ist, aber die Ausgabe wird jetzt umgeleitet.
Dann können Sie verwenden printf
wie gewohnt, aber die Ergebnisse werden in der txt-Datei sein, anstatt direkt auf dem Bildschirm angezeigt zu werden:
printf("Are you kidding me? \n");
PS:
Dies gibt nur eine intuitive Erklärung, Sie müssen möglicherweise die Manpage oder detaillierte Informationen überprüfen. Eigentlich sagen wir hier „kopieren“, sie kopieren nicht alles.
Die Datei-ID bezieht sich hier auf den Handler der Datei. Der oben erwähnte Dateideskriptor ist eine Struktur der Informationen der Aufzeichnungsdatei.
Diese Antwort braucht ein gutes s/fprintf/printf/g
. fprintf
schreibt in den explizit benannten Dateideskriptor. printf
schreibt an stdout
.
– Mahmoud Al-Qudsi
23. Oktober 2017 um 17:50 Uhr
Tim Post
Wenn Sie neugierig auf POSIX-Funktionen sind, insbesondere solche, die sich selbst zu duplizieren scheinen, ist es im Allgemeinen gut, dies zu tun Überprüfen Sie die Norm selbst. Unten sehen Sie normalerweise Beispiele sowie Begründungen für die Implementierung (und Existenz) von beiden.
In diesem Fall:
Die folgenden Abschnitte sind informativ.
Standardausgabe in eine Datei umleiten
Das folgende Beispiel schließt die Standardausgabe für die aktuellen Prozesse und weist die Standardausgabe neu der Datei zu, auf die verwiesen wird pfd
und schließt den ursprünglichen Dateideskriptor, um ihn zu bereinigen.
#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...
Das folgende Beispiel leitet Nachrichten von um stderr
zu stdout
.
#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...
Keiner.
Das dup()
und dup2()
Funktionen sind überflüssig. Ihre Dienste werden auch von der bereitgestellt fcntl()
Funktion. Sie wurden hauptsächlich aus historischen Gründen in diesen Band von IEEE Std 1003.1-2001 aufgenommen, da viele existierende Anwendungen sie verwenden.
Während das gezeigte kurze Codesegment im Verhalten sehr ähnlich ist dup2()
, ist eine konforme Implementierung basierend auf anderen Funktionen, die in diesem Band von IEEE Std 1003.1-2001 definiert sind, wesentlich komplexer. Am wenigsten offensichtlich ist der mögliche Effekt einer Signalfangfunktion, die zwischen Schritten aufgerufen werden könnte und Dateideskriptoren zuordnen oder freigeben könnte. Dies könnte durch Blockieren von Signalen vermieden werden.
Das dup2()
Die Funktion ist nicht als veraltet gekennzeichnet, da sie eine typsichere Version der Funktionalität darstellt, die in einer typunsicheren Version von bereitgestellt wird fcntl()
. Es wird in der POSIX-Ada-Bindung verwendet.
Das dup2()
Funktion ist nicht für den Einsatz in kritischen Regionen als Synchronisationsmechanismus vorgesehen.
In der Beschreibung von [EBADF], wird der Fall, dass Fildes außerhalb des Bereichs liegen, durch den gegebenen Fall abgedeckt, dass Fildes nicht gültig sind. Die Beschreibungen für fildes
und fildes2
unterschiedlich sind, weil die einzige Art von Invalidität relevant ist fildes2
ist, ob es außerhalb des Bereichs liegt; das heißt, es spielt keine Rolle, ob fildes2
bezieht sich auf eine geöffnete Datei, wenn die dup2()
Anruf erfolgt.
Keiner.
close()
, fcntl()
, open()
der Basisdefinitionsband von IEEE Std 1003.1-2001, <unistd.h>
Erstveröffentlichung in Ausgabe 1. Abgeleitet von Ausgabe 1 der SVID.
Was ist die Definition von Umleitung? Alles, was Sie auf fd1 schreiben, wird auch auf fd2 geschrieben
– Bionix1441
27. September 2016 um 8:13 Uhr
Das ist nicht hilfreich. Sie hätten genauso gut RTFM sagen können.
– Andreas
21. September 2017 um 15:58 Uhr
Vinit Dhatrak
Ein praktisches Beispiel ist das Umleiten von Ausgabemeldungen an einen anderen Stream wie eine Protokolldatei. Hier ist ein Beispielcode für die E/A-Umleitung.
Bitte beziehen Sie sich hier auf den ursprünglichen Beitrag
#include <stdio.h>
main()
{
int fd;
fpos_t pos;
printf("stdout, ");
fflush(stdout);
fgetpos(stdout, &pos);
fd = dup(fileno(stdout));
freopen("stdout.out", "w", stdout);
f();
fflush(stdout);
dup2(fd, fileno(stdout));
close(fd);
clearerr(stdout);
fsetpos(stdout, &pos); /* for C9X */
printf("stdout again\n");
}
f()
{
printf("stdout in f()");
}
maitreyak
Die E/A-Umleitung in der Shell würde höchstwahrscheinlich mithilfe von dup2/fcnlt-Systemaufrufen implementiert.
Wir können das leicht nachahmen $program 2>&1 > logfile.log
Art der Umleitung mit der Funktion dup2.
Das folgende Programm leitet sowohl stdout als auch stderr um. ie emuliert das Verhalten von $program 2>&1 > output
mit dup2.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int
main(void){
int close_this_fd;
dup2(close_this_fd = open("output", O_WRONLY), 1);
dup2(1,2);
close(close_this_fd);
fprintf(stdout, "standard output\n");
fprintf(stderr, "standard error\n");
fflush(stdout);
sleep(100); //sleep to examine the filedes in /proc/pid/fd level.
return;
}
vagrant@precise64:/vagrant/advC$ ./a.out
^Z
[2]+ Stopped ./a.out
vagrant@precise64:/vagrant/advC$ cat output
standard error
standard output
vagrant@precise64:/vagrant/advC$ ll /proc/2761/fd
total 0
dr-x------ 2 vagrant vagrant 0 Jun 20 22:07 ./
dr-xr-xr-x 8 vagrant vagrant 0 Jun 20 22:07 ../
lrwx------ 1 vagrant vagrant 64 Jun 20 22:07 0 -> /dev/pts/0
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 1 -> /vagrant/advC/output
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 2 -> /vagrant/advC/output
Siehe auch dup2 / dup – warum sollte ich einen Dateideskriptor duplizieren müssen?
– Matheus Santana
13. März 2018 um 18:07 Uhr