Kann jemand erklären, was dup() in C tut?

Lesezeit: 4 Minuten

Ich kenne das dup, dup2, dup3 “Erstellen Sie eine Kopie des Dateideskriptors oldfd“(aus Manpages). Ich kann es jedoch nicht verdauen.

Wie ich weiß, sind Dateideskriptoren nur Zahlen um Dateispeicherorte und ihre Richtung (Eingabe/Ausgabe) zu verfolgen. Wäre es nicht einfacher, einfach

fd=fd2;

Wann immer wir einen Dateideskriptor duplizieren wollen?

Und etwas anderes..

dup() verwendet den unbenutzten Deskriptor mit der niedrigsten Nummer für den neuen Deskriptor.

Bedeutet das, dass es auch als Wert nehmen kann stdin, stdout oder stderr wenn wir davon ausgehen, dass wir haben nah dran()-ed einer von denen?

  • Bei der ersten Frage müssen Sie bedenken, dass der Kernel die Anzahl der geöffneten Datei-Handles verfolgt. dup ist Ihre Art, dem Kernel mitzuteilen, dass er einen anderen dieser Datei-Handles (der sich auf dieselbe Datei bezieht) bis zu Ihnen verfolgt close es.

    – Benutzer786653

    22. Oktober 2011 um 18:17 Uhr


Benutzer-Avatar
Pithikos

Ich wollte nur auf die zweite Frage antworten, nachdem ich ein bisschen herumexperimentiert hatte.

Die Antwort ist JAWOHL. Ein von Ihnen erstellter Dateideskriptor kann die Werte 0, 1, 2 annehmen, wenn stdin, stdout oder stderr geschlossen sind.

Beispiel:

close(1);     //closing stdout
newfd=dup(1); //newfd takes value of least available fd number

Wo dies mit Dateideskriptoren passiert:

0 stdin     .--------------.     0 stdin     .--------------.     0 stdin
1 stdout   =|   close(1)   :=>   2 stderr   =| newfd=dup(1) :=>   1 newfd
2 stderr    '--------------'                 '--------------'     2 stderr

  • Wieder tauchte eine Frage auf: Wie kann ich dup() ein Dateideskriptor, den ich bereits geschlossen habe?

    – Pithikos

    19. August 2014 um 9:19 Uhr

  • Aus der Definition verwendet dup() den unbenutzten Deskriptor mit der niedrigsten Nummer für den neuen Deskriptor. Und wenn Sie einen Dateideskriptor schließen, bedeutet dies, dass er zur Verwendung verfügbar ist.

    – Raghu Srikanth Reddy

    25. August 2014 um 6:52 Uhr

Ein Dateideskriptor ist etwas mehr als eine Zahl. Es trägt auch verschiedene halbversteckte Zustände mit sich (ob es geöffnet ist oder nicht, auf welche Dateibeschreibung es sich bezieht und auch einige Flags). dup dupliziert diese Informationen, sodass Sie zB die beiden Deskriptoren unabhängig voneinander schließen können. fd=fd2 nicht.

  • Dies. Die “Nummer” ist ein Index in eine Datenstruktur, die vom Kernel verwaltet wird. Das dup Funktionsfamilie klonen Sie den Zustand eines Knotens in dieser Datenstruktur und übergeben Sie den Index an den neuen Knoten.

    – dmckee — Ex-Moderator-Kätzchen

    22. Oktober 2011 um 19:46 Uhr

  • @dmckee: “Kernel” und “Index” sind Implementierungsdetails. Es gibt einige Daten, die mit “der Nummer” verbunden sind, die nicht direkt vom Programm manipuliert werden können und die von geklont werden dup(). Das ist alles, was der Programmierer wissen muss. Übrigens ist es kein sehr interessantes Datenstück, es sind nur ein paar Flags und ein Index zu den wirklich interessanten Daten (der offenen Dateibeschreibung). nicht geklont von dup().

    – n. 1.8e9-wo-ist-meine-Aktie m.

    22. Oktober 2011 um 20:10 Uhr

Benutzer-Avatar
Richard Pennington

Angenommen, Sie schreiben ein Shell-Programm und möchten stdin und stdout in einem Programm umleiten, das Sie ausführen möchten. Es könnte etwa so aussehen:

fdin = open(infile, O_RDONLY);
fdout = open(outfile, O_WRONLY);
// Check for errors, send messages to stdout.
...
int pid = fork(0);
if(pid == 0) {
    close(0);
    dup(fdin);
    close(fdin);
    close(1);
    dup(fdout);
    close(fdout);
    execvp(program, argv);
}
// Parent process cleans up, maybe waits for child.
...

dup2() ist ein etwas bequemerer Weg, es zu tun. close() dup() kann ersetzt werden durch:

dup2(fdin, 0);
dup2(fdout, 1);

Der Grund, warum Sie dies tun möchten, ist, dass Sie Fehler an stdout (oder stderr) melden möchten, damit Sie sie nicht einfach schließen und eine neue Datei im untergeordneten Prozess öffnen können. Zweitens wäre es eine Verschwendung, den Fork durchzuführen, wenn einer der Aufrufe von open() einen Fehler zurückgeben würde.

Das Wichtigste an dup() ist, dass es die kleinste verfügbare Ganzzahl für einen neuen Dateideskriptor zurückgibt. Das ist die Grundlage der Weiterleitung:

int fd_redirect_to = open("file", O_CREAT);
close(1); /* stdout */
int fd_to_redirect = dup(fd_redirect_to); /* magically returns 1: stdout */
close(fd_redirect_to); /* we don't need this */

Danach geht alles, was in den Dateideskriptor 1 (stdout) geschrieben wird, auf magische Weise in “Datei”.

Beispiel:

close(1);     //closing stdout
newfd=dup(1); //newfd takes value of least available fd number

Wo dies mit Dateideskriptoren passiert:

0 stdin     .--------------.     0 stdin     .--------------.     0 stdin
1 stdout   =|   close(1)   :=>   2 stderr   =| newfd=dup(1) :=>   1 newfd
2 stderr    '--------------'                 '--------------'     2 stderr

Wieder tauchte eine Frage auf: Wie kann ich dup() ein Dateideskriptor, den ich bereits geschlossen habe?

Ich bezweifle, dass Sie obiges Experiment mit dem gezeigten Ergebnis durchgeführt haben, denn das wäre nicht normgerecht – vgl. dup:

Das dup() Funktion schlägt fehl, wenn:

[EBADF]
Das Fildes Argument ist kein gültiger offener Dateideskriptor.

Also, nach der gezeigten Codesequenz, newfd muss nicht sein 1sondern eher -1und errno EBADF.

Benutzer-Avatar
Karel Frajták

Sieh dir das an Seitestdout kann als Alias ​​bezeichnet werden dup(1)

Benutzer-Avatar
b3h3m0th

Nur ein Tipp zu “Duplizieren der Standardausgabe“.

Auf einigen Unix-Systemen (aber nicht GNU/Linux)

fd = open("/dev/fd/1", O_WRONLY);

es ist äquivalent zu:

fd = dup(1);

1365100cookie-checkKann jemand erklären, was dup() in C tut?

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

Privacy policy