Я знаю, что делает dup
или dup2
, но я понятия не имею, когда он будет использоваться. Какие-нибудь практические примеры? Спасибо.
Практические примеры используют dup или dup2
Ответ 1
Одним из примеров использования будет перенаправление ввода-вывода. Для этого вы создаете дочерний процесс и закрываете дескрипторы файла stdin или stdout (0 и 1), а затем вы делаете dup() в другом выбранном вами filedescriptor, который теперь будет сопоставлен с самым низким доступным файловым дескриптором, который находится в этом случай 0 или 1.
Используя это, вы можете теперь выполнить любой дочерний процесс, который, возможно, не знает о вашем приложении и всякий раз, когда ребенок записывает на stdout (или читает из stdin, независимо от того, что вы настроили), данные записываются на предоставленный filedescriptor.
Оболочки используют это для реализации коммандос с трубами, например. /bin/ls | more
, соединяя stdout одного процесса с stdin другого.
Ответ 2
Лучший сценарий для понимания dup и dup2 - перенаправление.
Первое, что нам нужно знать, это то, что система имеет 3 идентификатора файлов по умолчанию (или переменные, указывающие выходные или входные источники), которые имеют дело с вводом и выводом. Они stdin
, stdout
, stderr
, в целых числах они 0
, 1
, 2
. Большинство функций, таких как fprintf
или cout
, напрямую выводятся на stdout
.
Если мы хотим перенаправить вывод, один из способов даст, например, fprintf
функцию дополнительных аргументов, указывающих in
и out
.
Однако есть более элегантный способ: мы можем перезаписать идентификаторы файлов по умолчанию, чтобы они указывали на файл, который мы хотим получить. dup
и dup2
работают именно в этой ситуации.
Начнем с простого примера: предположим, что мы хотим перенаправить вывод fprintf
в txt файл с именем "chinaisbetter.txt" . Прежде всего, нам нужно открыть этот файл
int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);
Затем мы хотим, чтобы stdout
указывал на "chinaisbetter.txt" с помощью функции dup:
dup2(fw,1);
Теперь stdout (1) указывает на дескриптор "chinaisbetter.txt" , хотя он все еще 1, но выход перенаправляется прямо сейчас.
Затем вы можете использовать printf
как обычно, но результаты будут в файле txt вместо прямого показа на экране:
printf("Are you kidding me? \n");
PS
-
Это просто дает интуитивное объяснение, вам может потребоваться проверить man-страницу или подробную информацию. На самом деле мы говорим "копировать" здесь, они не копируют все.
-
Идентификатор файла здесь относится к обработчику файла. Описанный выше файловый дескриптор представляет собой структуру данных файлов записей.
Ответ 3
Когда вам интересно о функциях POSIX, особенно тех, которые, похоже, дублируют себя, обычно хорошо проверить сам стандарт. Внизу вы обычно увидите примеры, а также рассуждения о реализации (и существовании) обоих.
В этом случае:
Следующие разделы являются информативными.
Примеры
Перенаправление стандартного вывода в файл
Следующий пример закрывает стандартный вывод для текущих процессов, повторно назначает стандартный вывод для перехода к файлу, на который ссылается pfd
, и закрывает исходный дескриптор файла для очистки.
#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...
Перенаправление сообщений об ошибках
Следующий пример перенаправляет сообщения от stderr
до stdout
.
#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...
Использование приложения
Отсутствует.
Обоснование
Функции dup()
и dup2()
являются избыточными. Их службы также предоставляются функцией fcntl()
. Они включены в этот объем IEEE Std 1003.1-2001 в основном по историческим причинам, поскольку многие существующие приложения используют их.
В то время как показанный короткий сегмент кода очень похож в поведении на dup2()
, соответствующая реализация, основанная на других функциях, определенных в этом томе IEEE Std 1003.1-2001, значительно сложнее. Наименее очевидным является возможный эффект функции улавливания сигнала, которая может быть вызвана между этапами, и выделять или освобождать файловые дескрипторы. Этого можно избежать, заблокировав сигналы.
Функция dup2()
не является устаревшей, поскольку она представляет собой безопасную версию функциональности, предоставляемую в небезопасной версии типа fcntl()
. Он используется в привязке POSIX Ada.
Функция dup2()
не предназначена для использования в критических областях в качестве механизма синхронизации.
В описании [EBADF] случай, когда fildes выходит за пределы диапазона, покрывается данным случаем, когда fildes недействительны. Описания для fildes
и fildes2
различны, потому что единственный вид недействительности, который имеет значение для fildes2
, - это вне диапазона; то есть, не имеет значения, относится ли fildes2
к открытому файлу при вызове dup2()
.
Будущие направления
Отсутствует.
См. также
close()
, fcntl()
, open()
, том базовых определений IEEE Std 1003.1-2001, <unistd.h>
История изменений
Первый выпущен в выпуске 1. Выведен из номера 1 из SVID.
Ответ 4
Один практический пример - перенаправление выходных сообщений на другой поток, например, на некоторый файл журнала. Вот пример кода для перенаправления ввода-вывода.
Пожалуйста, обратитесь к оригинальному сообщению здесь
#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()");
}