Я пытаюсь понять использование dup2
и dup
.
На странице руководства:
DESCRIPTION
dup and dup2 create a copy of the file descriptor oldfd.
After successful return of dup or dup2, the old and new descriptors may
be used interchangeably. They share locks, file position pointers and
flags; for example, if the file position is modified by using lseek on
one of the descriptors, the position is also changed for the other.
The two descriptors do not share the close-on-exec flag, however.
dup uses the lowest-numbered unused descriptor for the new descriptor.
dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.
RETURN VALUE
dup and dup2 return the new descriptor, or -1 if an error occurred
(in which case, errno is set appropriately).
Зачем мне нужен этот системный вызов? какой толк в дублировании дескриптора файла?
Если у меня есть файловый дескриптор, зачем мне делать его копию?
Я был бы признателен, если бы вы могли объяснить и привести мне пример, где dup2
/ dup
необходимо.
Благодарность
c
linux
operating-system
system-calls
ЯНВАРЬ
источник
источник
dup
илиdup2
? Вам нужно позвонить,pipe(2)
а затем иметь один из файловых дескрипторов,dup
например,STDIN_FILENO
Ответы:
Системный вызов dup дублирует существующий дескриптор файла, возвращая новый, который относится к тому же базовому объекту ввода-вывода.
Dup позволяет оболочкам реализовывать такие команды:
ls existing-file non-existing-file > tmp1 2>&1
2> & 1 указывает оболочке дать команде файловый дескриптор 2, который является дубликатом дескриптора 1. (т.е. stderr и stdout указывают на тот же fd).
Теперь сообщение об ошибке для вызова ls для несуществующего файла и правильный вывод ls для существующего файла отображаются в файле tmp1 .
В следующем примере кода выполняется программа wc со стандартным вводом, подключенным к концу канала для чтения.
int p[2]; char *argv[2]; argv[0] = "wc"; argv[1] = 0; pipe(p); if(fork() == 0) { close(STDIN); //CHILD CLOSING stdin dup(p[STDIN]); // copies the fd of read end of pipe into its fd i.e 0 (STDIN) close(p[STDIN]); close(p[STDOUT]); exec("/bin/wc", argv); } else { write(p[STDOUT], "hello world\n", 12); close(p[STDIN]); close(p[STDOUT]); }
Потомок дублирует конец чтения на дескриптор файла 0, закрывает дескрипторы файла в p и выполняет wc. Когда wc читает из стандартного ввода, он читает из канала.
Вот как каналы реализуются с использованием dup, хорошо, что одно использование dup теперь вы используете канал для создания чего-то еще, в этом прелесть системных вызовов, вы строите одну вещь за другой, используя инструменты, которые уже есть, этот инструмент был построен с использованием что-то еще и так далее .. В конце концов, системные вызовы - это самые основные инструменты, которые вы получаете в ядре
Ура :)
источник
dup
полезно для звонящего, а не для самойls
программы? Есть ли польза отdup
использования в программе, такой как сама ls, если уже есть доступ к файлу? Здесь, например,ls
записываются ошибки,2
которые жестко запрограммированы, поэтому у меня есть способ переопределить их как потребителяls
. Я думаю, это тонкий момент, нет?dup(p[STDIN])
но потом отбрасываете результат. Вы хотели использоватьdup2(p[STDIN], 0)
?dup
возвращает «дескриптор с наименьшим номером, который в настоящее время не используется процессом». Поскольку fd 0 был только что закрыт, онdup
должен вернуть 0.dup2
Ясно, какой fd следует использовать, а не просто использовать наименьший свободный fd, поэтому я бы предпочел это.exec*
из многопоточного процесса. Но я не эксперт поДругая причина для дублирования файлового дескриптора - использование его с
fdopen
.fclose
закрывает переданный дескриптор файлаfdopen
, поэтому, если вы не хотите, чтобы исходный дескриптор файла был закрыт, вы должныdup
сначала продублировать его .источник
fdopen()
похоже, не дублирует файловый дескриптор, он просто создает буфер в пользовательском пространстве.dup
использовать fd, прежде чем передавать его,fdopen
посколькуfclose
закроет его.FILE
дескриптор для доступа к уже существующему открытому файлу через интерфейсы stdio, вам нужно вызватьfclose
для освобождения этогоFILE
дескриптора. Если вы хотите продолжать использовать лежащий в основе открытый файл или ваша программная архитектура такова, что это будет исходный код «владельца» для файлового дескриптораclose
, то факт, что онfclose
также закрывает нижележащий файловый дескриптор, который вы передали,fdopen
является проблемой. Вы можете избежать этой проблемы, используяdup
для создания нового файлового дескриптора для того же открытого файла, кfdopen
которому нужно перейти , чтобыfclose
не закрыть исходный файл .FILE
, а не копировать его. Это то, о чем пользователи должны знать. Потребители, которым необходимо сохранить полезныйfd
дескриптор в дополнение кFILE
объекту, должны дублироватьfd
. Вот и все.FILE
когда вы передаете ему владение.dup используется для перенаправления вывода процесса.
Например, если вы хотите сохранить вывод процесса, вы дублируете вывод (fd = 1), перенаправляете дублированный fd в файл, затем разветвляете и выполняете процесс, а когда процесс завершается, вы снова перенаправляете сохранил fd для вывода.
источник
Обратите внимание на некоторые моменты, связанные с dup / dup2.
dup / dup2 - Технически цель состоит в том, чтобы разделить одну запись таблицы файлов внутри одного процесса с помощью разных дескрипторов. (Если мы выполняем разветвление, дескриптор по умолчанию дублируется в дочернем процессе, и запись в таблице файлов также является общей).
Это означает, что с помощью функции dup / dup2 у нас может быть более одного дескриптора файла с возможно разными атрибутами для одной записи открытой таблицы файлов.
(Хотя, похоже, в настоящее время только флаг FD_CLOEXEC является единственным атрибутом для файлового дескриптора).
http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html
dup(fd) is equivalent to fcntl(fd, F_DUPFD, 0); dup2(fildes, fildes2); is equivalent to close(fildes2); fcntl(fildes, F_DUPFD, fildes2);
Различия (для последнего) - помимо некоторого значения errno между dup2 и fcntl close, за которым следует fcntl, могут возникать условия гонки, поскольку задействованы два вызова функций.
Подробности можно узнать на http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html.
Пример использования -
Один интересный пример реализации управления заданиями в оболочке, где можно увидеть использование dup / dup2 .. по ссылке ниже
http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs
источник