Может ли кто-нибудь объяснить, что делает dup () в C?

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

Поскольку я знаю, что файловые дескрипторы – это просто цифры, чтобы отслеживать расположение файлов и их направление (ввод / вывод). Было бы проще просто

fd=fd2; 

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

И что-нибудь еще..

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

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

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

Ответ: ДА . Дескриптор файла, который вы делаете, может принимать значения 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 

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

Самая важная вещь о 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 (stdout), волшебным образом переходит в «файл».

Предположим, вы пишете программу оболочки, и вы хотите перенаправить 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 () возвратил ошибку.

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

Просто совет о « дублировании стандартного вывода ».

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

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

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

 fd = dup(1); 

Пример:

 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]
Аргумент fildes не является допустимым дескриптором открытого файла.

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

dup () и dup2 ()

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

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

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

int dup (file_descriptor)

int dup2 (file_descriptor1, file_descriptor2)