Подтвердить что ты не робот

Повторное открытие дескрипторов файлов stdout и stdin после их закрытия

Я пишу функцию, которая, учитывая аргумент, либо перенаправляет stdout в файл, либо читает stdin из файла. Для этого я закрываю дескриптор файла, связанный с stdout или stdin, поэтому, когда я открываю файл, он открывается под дескриптором, который я только что закрыл. Это работает, но проблема в том, что как только это будет сделано, мне нужно восстановить stdout и stdin, чтобы они действительно были.

Что я могу сделать для stdout открыто ( "/dev/tty", O_WRONLY); Но я не уверен, почему это работает, и что еще более важно, я не знаю эквивалентного утверждения для stdin.

Итак, для stdout

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

и для stdin

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

Ответ 1

Вы должны использовать dup() и dup2() для клонирования дескриптора файла.

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);

Однако, есть небольшая деталь, с которой вы, возможно, захотите быть осторожной (от человека dup):

Два дескриптора не разделяют флаги дескриптора файла ( крупный на execflag). Флаг close-on-exec (FD_CLOEXEC; см. Fcntl (2)) для дубликата дескриптора выключено.

Если это проблема, возможно, вам придется восстановить флаг close-on-exec, возможно, используя dup3() вместо dup2(), чтобы избежать условий гонки.

Кроме того, имейте в виду, что если ваша программа многопоточна, другие потоки могут случайно записать/прочитать ваш переназначенный stdin/stdout.

Ответ 2

Я думаю, что вы можете "сохранить" дескрипторы перед перенаправлением:

int save_in, save_out;

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

Позже вы можете использовать dup2 для их восстановления:

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

Я не делаю никаких ошибок в этом примере - вы должны.

Ответ 3

Вы можете создать дочерний процесс и настроить перенаправление только внутри дочернего элемента. Затем подождите, пока ребенок закончит работу, и продолжите работу в родительском процессе. Таким образом, вам не нужно беспокоиться о том, чтобы полностью изменить свое перенаправление.

Просто найдите примеры кода, используя fork() и wait().