Erneutes Öffnen von stdout- und stdin-Dateideskriptoren nach dem Schließen

Lesezeit: 3 Minuten

Ich schreibe eine Funktion, die bei einem Argument entweder die Standardausgabe in eine Datei umleitet oder die Standardausgabe aus einer Datei liest. Dazu schließe ich den mit stdout oder stdin verknüpften Dateideskriptor, sodass die Datei beim Öffnen unter dem gerade geschlossenen Deskriptor geöffnet wird. Das funktioniert, aber das Problem ist, dass ich, sobald dies erledigt ist, die stdout und stdin so wiederherstellen muss, wie sie wirklich sein sollten.

Was ich für stdout tun kann, ist open(“/dev/tty”,O_WRONLY); Aber ich bin mir nicht sicher, warum das funktioniert, und was noch wichtiger ist, ich kenne keine entsprechende Anweisung für stdin.

Also habe ich für stdout

close(1);
if (creat(filePath, O_RDWR) == -1)
{
    exit(1);
}

und für stdin

close(0);
if (open(filePath, O_RDONLY) == -1)
{
    exit(1);
}

  • O_RDWR ist für open flags Parameter nicht für creat mode Parameter.

    – Werner Henze

    21. März 2016 um 12:22 Uhr


Benutzeravatar von Ambroz Bizjak
Ambroz Bizjak

Sie sollten dup() und dup2() verwenden, um einen Dateideskriptor zu klonen.

int stdin_copy = dup(0);
int stdout_copy = dup(1);
close(0);
close(1);

int file1 = open(...);
int file2 = open(...);

< do your work. file1 and file2 must be 0 and 1, because open always returns lowest unused fd >

close(file1);
close(file2);
dup2(stdin_copy, 0);
dup2(stdout_copy, 1);
close(stdin_copy);
close(stdout_copy);

Es gibt jedoch ein kleines Detail, mit dem Sie vielleicht vorsichtig sein sollten (von man dup):

Die beiden Deskriptoren teilen sich keine Dateideskriptor-Flags (das close-on-execfflag). Das Close-on-exec-Flag (FD_CLOEXEC; siehe fcntl(2)) für den doppelten Deskriptor ist ausgeschaltet.

Wenn dies ein Problem ist, müssen Sie möglicherweise das Close-on-exec-Flag wiederherstellen, möglicherweise mit dup3() anstelle von dup2(), um Racebedingungen zu vermeiden.

Beachten Sie auch, dass andere Threads versehentlich in Ihre neu zugeordnete stdin/stdout schreiben/lesen können, wenn Ihr Programm multithreaded ist.

  • Es gibt andere Probleme, wenn Sie Multithreading verwenden – wenn ein anderer Thread eine Datei zwischen Ihnen öffnet close(0) (oder close(1)) und das entsprechende open(...), dann wird seine Datei zu stdin (oder stdout). Es ist viel besser zu verwenden dup2() (oder dup3), um zu erzwingen, dass der Dateideskriptor 0 (oder 1) ist, anstatt sich auf das Verhalten „am wenigsten unbenutzt“ zu verlassen.

    – Psmärchen

    6. September 2015 um 22:26 Uhr

  • Gibt es eine Möglichkeit, das zu tun, ohne es zu klonen (angenommen, wir können weder dup noch dup2 verwenden)?

    – Milad

    29. Oktober 2019 um 6:49 Uhr

Ich denke, Sie können die Deskriptoren “speichern”. vor der Umleitung:

int save_in, save_out;

save_in = dup(STDIN_FILENO);
save_out = dup(STDOUT_FILENO);

Später können Sie verwenden dup2 um sie wiederherzustellen:

/* Time passes, STDIN_FILENO isn't what it used to be. */
dup2(save_in, STDIN_FILENO);

Ich mache in diesem Beispiel keine Fehlerprüfung – Sie sollten es tun.

Sie könnten einen untergeordneten Prozess erstellen und die Umleitung nur innerhalb des untergeordneten Prozesses einrichten. Warten Sie dann, bis der untergeordnete Prozess beendet ist, und arbeiten Sie im übergeordneten Prozess weiter. Auf diese Weise müssen Sie sich überhaupt keine Gedanken über die Umkehrung Ihrer Weiterleitung machen.

Suchen Sie einfach nach Codebeispielen mit fork() und wait().

1387520cookie-checkErneutes Öffnen von stdout- und stdin-Dateideskriptoren nach dem Schließen

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

Privacy policy