Главная » 2017 » Ноябрь » 17 » man 2 dup
01:33
man 2 dup

SEO sprint - Всё для максимальной раскрутки!





ИМЯ


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



ОБЗОР


#include <unistd.h>

int dup(int oldfd);
int dup2(int oldfd, int newfd);

#define _GNU_SOURCE /* Смотрите feature_test_macros(7) */
#include <fcntl.h> /* Определение констант O_* */
#include <unistd.h>

int dup3(int oldfd, int newfd, int flags);



ОПИСАНИЕ


Системный вызов dup() создаёт копию файлового дескриптора oldfd, используя для
нового дескриптора самый маленький свободный номер файлового дескриптора.

После успешного выполнения старый и новый файловые дескрипторы являются
взаимозаменяемыми. Они указывают на одно и то же открытое файловое описание
(смотрите open(2)) и поэтому имеют общее файловое смещение и флаги состояния
файла; например, если файловое смещение изменить с помощью lseek(2) через один из
файловых дескрипторов, то смещение изменится и для другого.

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

dup2()
Системный вызов dup2() выполняет ту же задачу, что и dup(), но вместо
использования самого маленького неиспользуемого номера файлового дескриптора, он
использует номер файлового дескриптора, указанного в newfd. Если файловый
дескриптор newfd уже открыт, то он закрывается перед повторным использованием.

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

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

* Если oldfd является некорректным файловым дескриптором, то вызов завершается с
ошибкой, а newfd не закрывается.

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

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

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

EBADF Значение newfd находится вне допустимого диапазона файловых дескрипторов
(смотрите описание RLIMIT_NOFILE в getrlimit(2)).

EBUSY (только в Linux) Может случиться в dup2() или dup3() при возникновении
состязательности вызовов open(2) и dup().

EINTR Вызов dup2() или dup3() был прерван каким-либо сигналом. Смотрите
signal(7).

EINVAL (dup3()) flags содержит некорректное значение.

EINVAL (dup3()) oldfd было равно newfd.

EMFILE Было достигнуто ограничение по количеству открытых файловых дескрипторов на
процесс (смотрите описание RLIMIT_NOFILE в getrlimit(2)).



ВЕРСИИ


Вызов dup3() был добавлен в Linux версии 2.6.27; поддержка в 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) {

Категория: (2) Системные вызовы ядра (функции языка Си) | Просмотров: 438 | Добавил: Администратор | Рейтинг: 0.0/0
Всего комментариев: 0
avatar