Praktische Beispiele verwenden dup oder dup2

Lesezeit: 6 Minuten

Benutzeravatar von pierrotlefou
pierrotlefou

ich weiß was dup / dup2 tut, aber ich habe keine Ahnung, wann es verwendet werden würde.

Irgendwelche praktischen Beispiele?

Vielen Dank.

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

    – Matheus Santana

    13. März 2018 um 18:07 Uhr


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

Benutzeravatar von ZijunLost
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, stderrin 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:

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

  2. 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

Benutzeravatar von Tim Post
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.

Beispiele

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 pfdund schließt den ursprünglichen Dateideskriptor, um ihn zu bereinigen.

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

Fehlermeldungen umleiten

Das folgende Beispiel leitet Nachrichten von um stderr zu stdout.

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

Anwendungsnutzung

Keiner.

Begründung

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.

Zukünftige Richtungen

Keiner.

Siehe auch

close(), fcntl(), open()der Basisdefinitionsband von IEEE Std 1003.1-2001, <unistd.h>

Geschichte verändern

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

Benutzeravatar von Vinit Dhatrak
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()");
}

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

1416240cookie-checkPraktische Beispiele verwenden dup oder dup2

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

Privacy policy