Scroll to navigation

dup(2) System Calls Manual dup(2)

ИМЯ

dup, dup2, dup3 - создать дубликат файлового дескриптора

LIBRARY

Standard C library (libc, -lc)

СИНТАКСИС

#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <fcntl.h>              /* Definition of O_* constants */
#include <unistd.h>
int dup3(int oldfd, int newfd, int flags);

ОПИСАНИЕ

The dup() system call allocates a new file descriptor that refers to the same open file description as the descriptor oldfd. (For an explanation of open file descriptions, see open(2).) The new file descriptor number is guaranteed to be the lowest-numbered file descriptor that was unused in the calling process.

After a successful return, the old and new file descriptors may be used interchangeably. Since the two file descriptors refer to the same open file description, they share file offset and file status flags; for example, if the file offset is modified by using lseek(2) on one of the file descriptors, the offset is also changed for the other file descriptor.

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

dup2()

The dup2() system call performs the same task as dup(), but instead of using the lowest-numbered unused file descriptor, it uses the file descriptor number specified in newfd. In other words, the file descriptor newfd is adjusted so that it now refers to the same open file description as oldfd.

If the file descriptor newfd was previously open, it is closed before being reused; the close is performed silently (i.e., any errors during the close are not reported by dup2()).

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

Также заметим следующее:

  • Если oldfd является некорректным файловым дескриптором, то вызов завершается с ошибкой, а newfd не закрывается.
  • Если oldfd является корректным файловым дескриптором, а номер newfd совпадает с oldfd, то dup2() не делает ничего и возвращает значение newfd.

dup3()

dup3() похож на dup2(). Отличия заключаются в следующем:

  • Вызывающий может принудительно установить флаг close-on-exec flag у нового файлового дескриптора, указав O_CLOEXEC в flags. Зачем это может быть нужно смотрите в open(2).
  • Если oldfd равно newfd, то dup3() выдает ошибку EINVAL.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

On success, these system calls return the new file descriptor. On error, -1 is returned, and errno is set to indicate the error.

ОШИБКИ

Значение oldfd не является открытым файловым дескриптором.
Значение newfd находится вне допустимого диапазона файловых дескрипторов (смотрите описание RLIMIT_NOFILE в getrlimit(2)).
(только в Linux) Может случиться в dup2() или dup3() при возникновении состязательности вызовов open(2) и dup().
Вызов dup2() или dup3() был прерван каким-либо сигналом. Смотрите signal(7).
(dup3()) flags содержит некорректное значение.
(dup3()) oldfd было равно newfd.
Было достигнуто ограничение по количеству открытых файловых дескрипторов на процесс (смотрите описание RLIMIT_NOFILE в getrlimit(2)).

ВЕРСИИ

dup3() was added in Linux 2.6.27; glibc support is available since glibc 2.9.

СТАНДАРТЫ

dup(), dup2(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.

dup3() есть только в Linux.

ЗАМЕЧАНИЯ

Ошибка, которую возвращает dup2(), отличается от той, что возвращает fcntl(…, F_DUPFD, …), когда newfd находится вне допустимых пределов. На некоторых системах dup2() также иногда возвращает EINVAL — как F_DUPFD.

Если был открыт newfd, то любые ошибки, о которых было бы сообщено close(2), теряются. Если это важно, то (если программа однонитевая и не выделяет файловые дескрипторы в обработчиках сигналов) правильней будет не закрывать newfd перед вызовом dup2(), из-за состязательности, описанной выше. Вместо этого можно использовать, например, такой код:


/* Получить копию «newfd», которую затем можно

использовать для проверки ошибок close(); ошибка EBADF
означает, что «newfd» не открыт. */
tmpfd = dup(newfd);
if (tmpfd == -1 && errno != EBADF) {
/* обработка неожидаемой ошибки dup(). */
} /* атомарное копирование «oldfd» в «newfd» */
if (dup2(oldfd, newfd) == -1) {
/* обработка ошибки dup2(). */
}
/* теперь проверим ошибки close() у файла, на который изначально
ссылался «newfd» */
if (tmpfd != -1) {
if (close(tmpfd) == -1) {
/* обработка ошибок закрытия. */
}
}

СМ. ТАКЖЕ

close(2), fcntl(2), open(2), pidfd_getfd(2)

ПЕРЕВОД

Русский перевод этой страницы руководства был сделан Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.

4 декабря 2022 г. Linux man-pages 6.02