Вопрос

Я знаю, что dup / dup2 есть, но я понятия не имею, когда это будет использовано.

Есть какие-нибудь практические примеры?

Спасибо.

Это было полезно?

Решение

Одним из примеров использования может быть перенаправление ввода-вывода.Для этого вы разветвляете дочерний процесс и закрываете файловые дескрипторы stdin или stdout (0 и 1), а затем выполняете dup() для другого выбранного вами filedescriptor, который теперь будет сопоставлен с наименьшим доступным файловым дескриптором, который в данном случае равен 0 или 1.

Используя это, теперь вы можете запустить любой дочерний процесс, который, возможно, не знает о вашем приложении, и всякий раз, когда дочерний процесс записывает в стандартный вывод (или считывает из стандартного интерфейса, что бы вы ни настроили), данные вместо этого записываются в предоставленный filedescriptor.

Оболочки используют это для реализации команд с помощью каналов, например /bin/ls | more подключив стандартный вывод одного процесса к стандартному идентификатору другого.

Другие советы

Лучший сценарий для понимания dup и dup2 - это перенаправление.
Первое, что нам нужно знать, это то, что в системе есть 3 идентификатора файлов по умолчанию (или переменные, указывающие выходные данные или источники ввода), которые имеют дело с вводом и выводом.Они такие stdin, stdout, stderr, в целых числах они равны 0,1,2.Большинство функций, таких как fprintf или cout выводятся непосредственно на stdout.
Если мы хотим перенаправить выходные данные, одним из способов является give, например, fprintf функция с дополнительными аргументами, указывающими in и out.
Однако есть более элегантный способ:мы можем перезаписать идентификаторы файлов по умолчанию, чтобы они указывали на файл, который мы хотим получить на выходе. dup и dup2 точно сработайте в этой ситуации.
Давайте начнем с одного простого примера:предположим, мы хотим перенаправить вывод fprintf в текстовый файл с именем "chinaisbetter.txt".Прежде всего, нам нужно открыть этот файл

int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);

Тогда мы хотим stdout чтобы указать к "chinaisbetter.txt" с помощью функции ДУП :

dup2(fw,1);

Теперь стандартный вывод (1) указывает на дескриптор "chinaisbetter.txt", хотя он по-прежнему равен 1, но вывод теперь перенаправляется.
Тогда вы можете использовать printf как обычно, но результаты будут в текстовом файле, а не отображаться непосредственно на экране:

printf("Are you kidding me? \n");

PS:

  1. Это просто дает интуитивно понятное объяснение, возможно, вам потребуется проверить справочную страницу или подробную информацию.На самом деле, мы говорим здесь "копировать", они копируют не все.

  2. Идентификатор файла здесь ссылается на обработчик файла.Упомянутый выше файловый дескриптор представляет собой структуру, в которой записывается информация о файле.

Когда вам интересны функции 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 и fildes2 отличаются, потому что единственный вид недействительности, который имеет отношение к fildes2 находится ли он вне зоны досягаемости;то есть, не имеет значения, будет ли fildes2 ссылается на открытый файл, когда dup2() звонок сделан.

Направления на будущее

Нет.

Смотрите также

close(), fcntl(), open(), объем базовых определений стандарта IEEE Std 1003.1-2001, <unistd.h>

История изменений

Впервые опубликовано в выпуске 1.Взято из выпуска 1 SVID.

Одним из практических примеров является перенаправление выходных сообщений в какой-либо другой поток, например в файл журнала.Вот пример кода для перенаправления ввода-вывода.
Пожалуйста, обратитесь к оригинальному сообщению здесь

#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()");
}

Перенаправление ввода-вывода в командной оболочке, скорее всего, будет реализовано с использованием системных вызовов dup2 / fcnlt.

Мы можем легко подражать $program 2>&1 > logfile.log тип перенаправления с использованием функции dup2.

Приведенная ниже программа перенаправляет как stdout, так и stderr .т.е. эмулирует поведение $program 2>&1 > output используя 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top