wake-up-neo.com

praktische Beispiele verwenden dup oder dup2

Ich weiß, was dup/dup2 tut, aber ich habe keine Ahnung, wann es benutzt wird.

Irgendwelche praktischen Beispiele?

Vielen Dank.

60
pierrotlefou

Ein Beispiel wäre die I/O-Umleitung. Dazu verzweigen Sie einen untergeordneten Prozess und schließen die Dateideskriptoren stdin oder stdout (0 und 1). Anschließend führen Sie ein dup () auf einem anderen Dateiskriptor Ihrer Wahl aus, der nun dem niedrigsten verfügbaren Dateideskriptor zugeordnet wird, der in diesem Ordner enthalten ist Fall 0 oder 1.

Mit dieser Funktion können Sie jetzt jeden untergeordneten Prozess ausführen, der möglicherweise Ihre Anwendung nicht kennt. Wenn das untergeordnete Element auf das Standardausgabegerät schreibt (oder von Standardeingabegerät gelesen wird, was immer Sie konfiguriert haben), werden die Daten stattdessen in den bereitgestellten Dateiskriptor geschrieben.

Shells verwenden dies, um Befehle mit Pipes zu implementieren, z. /bin/ls | more durch Verbinden des stdout eines Prozesses mit dem stdin des anderen.

59
Alfonso

Das beste Szenario, um dup und dup2 zu verstehen, ist die Umleitung.
Das erste, was wir wissen müssen, ist, dass das System 3 Standard-Datei-IDs (oder Variablen, die Ausgabe- oder Eingabequellen angeben) enthält, die sich mit der Eingabe und Ausgabe befassen. Sie sind stdin, stdout, stderr, in ganzen Zahlen 0, 1, 2. Die meisten Funktionen wie fprintf oder cout werden direkt an stdout ausgegeben. 
Wenn wir die Ausgabe umleiten möchten, gibt es eine Möglichkeit, zum Beispiel fprintf function weitere Argumente anzugeben, die in und out angeben. 
Es gibt jedoch einen eleganteren Weg: Wir können die Standard-Datei-IDs überschreiben, damit sie auf die Datei zeigen, die die Ausgabe erhalten soll. dup und dup2 funktionieren in dieser Situation genau.
Wir beginnen jetzt mit einem einfachen Beispiel: Angenommen, wir möchten die Ausgabe von fprintf in eine txt-Datei mit dem Namen "chinaisbetter.txt" umleiten. Zunächst müssen wir diese Datei öffnen 

int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);

Dann möchten wir, dass stdout mit der dup-Funktion auf "chinaisbetter.txt" verweist:

dup2(fw,1);

Nun verweist stdout (1) auf den Deskriptor von "chinaisbetter.txt", obwohl es immer noch 1 ist, aber die Ausgabe wird jetzt umgeleitet.
Dann können Sie printf wie gewohnt verwenden, aber die Ergebnisse werden in der TXT-Datei angezeigt, anstatt direkt auf dem Bildschirm angezeigt zu werden:

printf("Are you kidding me? \n");

PS:

  1. Dies ist 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.

  2. Die Datei-ID bezieht sich hier auf den Handler der Datei. Der oben erwähnte Dateideskriptor ist eine Struktur der Datensatzdatei.

20
ZijunLost

Wenn Sie neugierig auf POSIX-Funktionen sind, insbesondere auf diejenigen, die sich scheinbar selbst duplizieren, ist es in der Regel gut, den Standard selbst prüfen . Unten sehen Sie in der Regel Beispiele sowie Gründe für die Implementierung (und Existenz) beider.

In diesem Fall:

Die folgenden Abschnitte sind informativ.

Beispiele

Umleiten der Standardausgabe in eine Datei

Das folgende Beispiel schließt die Standardausgabe für die aktuellen Prozesse, weist die Standardausgabe erneut zu, um zu der mit pfd referenzierten Datei zu wechseln, und schließt den ursprünglichen Dateideskriptor zum Bereinigen.

#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...

Fehlermeldungen umleiten

Im folgenden Beispiel werden Nachrichten von stderr an stdout umgeleitet.

#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...

Anwendungsnutzung

Keiner.

Begründung

Die Funktionen dup() und dup2() sind redundant. Ihre Dienste werden auch von der Funktion fcntl() bereitgestellt. Sie wurden in diesem Band von IEEE Std 1003.1-2001 hauptsächlich aus historischen Gründen aufgenommen, da viele vorhandene Anwendungen sie verwenden.

Während das dargestellte kurze Codesegment dem Verhalten von dup2() sehr ähnlich ist, ist eine konforme Implementierung, die auf anderen Funktionen basiert, die in diesem Band von IEEE Std 1003.1-2001 definiert sind, erheblich komplexer. Am offensichtlichsten ist der mögliche Effekt einer Signalfangfunktion, die zwischen Schritten aufgerufen werden kann, um Dateideskriptoren zuzuordnen oder freizugeben. Dies könnte durch Blockieren von Signalen vermieden werden.

Die dup2()-Funktion ist nicht als veraltet gekennzeichnet, da sie eine typsichere Version der Funktionalität darstellt, die in einer typ-unsicheren Version von fcntl() bereitgestellt wird. Es wird in der POSIX Ada-Bindung verwendet.

Die Funktion dup2() ist nicht für die Verwendung 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 von Fildes, die nicht gültig sind, abgedeckt. Die Beschreibungen für fildes und fildes2 unterscheiden sich, da die einzige Art von Invalidität, die für fildes2 relevant ist, die Frage ist, ob sie außerhalb des gültigen Bereichs liegt. es spielt also keine Rolle, ob fildes2 auf eine geöffnete Datei verweist, wenn der Aufruf dup2() erfolgt.

Zukünftige Richtungen

Keiner.

Siehe auch

close(), fcntl(), open(), das Volume mit den Basisdefinitionen von IEEE Std 1003.1-2001, <unistd.h>

Geschichte verändern

Erstveröffentlichung in Ausgabe 1. Abgeleitet von Ausgabe 1 der SVID.

9
Tim Post

Ein praktisches Beispiel ist das Umleiten von Ausgabenachrichten an einen anderen Stream, wie z. Hier ist ein Beispielcode für die E/A-Umleitung.
Bitte beziehen Sie sich auf den Originalbeitrag hier

#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()");
}
5
vinit dhatrak

Die E/A-Umleitung in der Shell würde höchstwahrscheinlich mithilfe von dup2/fcnlt-Systemaufrufen implementiert.

Wir können den Umleitungstyp $program 2>&1 > logfile.log Einfach mit der Funktion dup2 emulieren.

Das folgende Programm leitet sowohl stdout als auch stderr .i.e um und emuliert das Verhalten von $program 2>&1 > output Unter Verwendung von 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;
}

[email protected]:/vagrant/advC$ ./a.out
^Z
[2]+  Stopped                 ./a.out
[email protected]:/vagrant/advC$ cat output
standard error
standard output
[email protected]:/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
1
maitreyak