Может кто-нибудь объяснить, что делает dup () в C? - PullRequest
19 голосов
/ 22 октября 2011

Я знаю, что dup, dup2, dup3 " создают копию дескриптора файла oldfd " (из man-страниц). Однако я не могу это переварить.

Как я знаю, дескрипторы файлов - это просто числа для отслеживания местоположения файлов и их направления (ввод / вывод). Не было бы проще просто

fd=fd2;

Всякий раз, когда мы хотим дублировать дескриптор файла?

И еще кое-что ..

dup () использует неиспользуемый дескриптор с наименьшим номером для нового дескриптора.

Означает ли это, что оно также может принимать значение stdin , stdout или stderr , если мы предположим, что у нас есть close () -ед один из тех?

Ответы [ 8 ]

15 голосов
/ 24 октября 2011

Просто хотел ответить на второй вопрос после небольшого эксперимента.

Ответ - ДА .Созданный вами файловый дескриптор может принимать значение 0, 1, 2, если stdin, stdout или stderr закрыты.

Пример:

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

Где это происходит с файловыми дескрипторами:

0 stdin     .--------------.     0 stdin     .--------------.     0 stdin
1 stdout   =|   close(1)   :=>   2 stderr   =| newfd=dup(1) :=>   1 newfd
2 stderr    '--------------'                 '--------------'     2 stderr
11 голосов
/ 22 октября 2011

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

6 голосов
/ 03 августа 2013

Единственная самая важная вещь в dup () - это то, что она возвращает наименьшее целое число, доступное для нового файлового дескриптора. Это основа перенаправления:

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 */

После этого все, что записано в файловый дескриптор 1 (стандартный вывод), волшебным образом переходит в «файл».

5 голосов
/ 22 октября 2011

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

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 () - немного более удобный способ сделать это close () dup () можно заменить на:

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

причина, по которой вы хотите это сделать, заключается в том, что вы хотите сообщать об ошибках в stdout (или stderr), поэтому вы не можете просто закрыть их и открыть новый файл в дочернем процессе.Во-вторых, было бы напрасно тратить вилку, если любой вызов open () вернул ошибку.

2 голосов
/ 22 октября 2011

см. Эту страницу , stdout может иметь псевдоним dup(1) ...

0 голосов
/ 22 октября 2018

dup () и dup2 () системный вызов

• Системный вызов dup () дублирует дескриптор открытого файла и возвращает новый файл Дескриптор.

• Новый дескриптор файла имеет следующие общие свойства с оригинал дескриптор файла: 1. относится к тому же открытому файлу или каналу. 2. имеет один и тот же файловый указатель - то есть оба файловых дескриптора имеют один файловый указатель. 3. имеет одинаковый режим доступа, будь то чтение, запись или чтение и запись.

• dup () гарантированно возвращает дескриптор файла с наименьшим доступным целочисленным значением. Именно из-за этой функции возвращается наименьший доступный дескриптор файла, который используется процессами для перенаправления ввода-вывода.

int dup (file_descriptor)

int dup2 (file_descriptor1, file_descriptor2)

0 голосов
/ 28 мая 2018

Пример:

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

Где это происходит с файловыми дескрипторами:

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

Снова возник вопрос: как мне dup() дескриптор файла, который я ужезакрыто?

Я сомневаюсь, что вы провели вышеупомянутый эксперимент с показанным результатом, потому что это не соответствовало бы стандартам - ср. dup :

Функция dup () не будет работать, если:

[EBADF] * 1023Аргумент * fildes не является допустимым дескриптором открытого файла.

Таким образом, после показанной кодовой последовательности newfd должно быть не 1, а -1, а errno EBADF.

0 голосов
/ 03 октября 2016

Просто подсказка о " дублировании стандартного вывода ".

В некоторых системах Unix (но не в GNU / Linux)

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

это эквивалентно:

fd = dup(1);
...