DUP - Linux手册页

时间:2019-08-20 17:58:37  来源:igfitidea点击:

Linux程序员手册 第2部分
更新日期: 2020-04-11

名称

dup,dup2,dup3-复制文件描述符

语法

#include <unistd.h>

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

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <fcntl.h>              /* Obtain O_* constant definitions */
#include <unistd.h>

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

说明

dup()系统调用使用新描述符的编号最小的未使用文件描述符创建文件描述符oldfd的副本。

成功返回后,旧文件描述符和新文件描述符可以互换使用。它们引用相同的打开文件描述(请参阅open(2)),因此共享文件偏移量和文件状态标志。例如,如果在文件描述符之一上使用lseek(2)修改了文件偏移,则另一个文件的偏移也将更改。

这两个文件描述符不共享文件描述符标志(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()相同,除了:

*
调用者可以通过在标志中指定O_CLOEXEC来强制为新文件描述符设置close-on-exec标志。有关为何可能有用的原因,请参见open(2)中相同标志的描述。
*
如果oldfd等于newfd,则dup3()失败,错误为EINVAL。

返回值

成功时,这些系统调用将返回新的文件描述符。如果出错,则返回-1,并正确设置errno。

错误说明

EBADF
oldfd不是打开的文件描述符。
EBADF
newfd超出了文件描述符的允许范围(请参阅getrlimit(2)中有关RLIMIT_NOFILE的讨论)。
EBUSY
(仅Linux)在与open(2)和dup()的竞争条件下,dup2()或dup3()可能会返回该值。
EINTR
dup2()或dup3()调用被信号中断;参见signal(7)。
EINVAL
(dup3())标志包含无效值。
EINVAL
(dup3())oldfd等于newfd。
EMFILE
已达到打开文件描述符数量的每个进程限制(请参阅getrlimit(2)中有关RLIMIT_NOFILE的讨论)。

版本

dup3()已在2.6.27版中添加到Linux;从2.9版开始提供glibc支持。

遵循规范

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

dup3()是特定于Linux的。

备注

当newfd超出范围时,dup2()返回的错误与fcntl(...,F_DUPFD,...)返回的错误不同。在某些系统上,dup2()有时也会返回EINVAL,例如F_DUPFD。

如果newfd已打开,则所有在close(2)时间已报告的错误都将丢失。如果这是令人关注的,那么-除非程序是单线程的并且不在信号处理程序中分配文件描述符,否则-正确的方法是在调用dup2()之前不要关闭newfd,因为上述竞争条件。相反,可以使用类似以下的代码:

/* Obtain a duplicate of 'newfd' that can subsequently
   be used to check for close() errors; an EBADF error
   means that 'newfd' was not open. */

tmpfd = dup(newfd);
if (tmpfd == -1 && errno != EBADF) {
    /* Handle unexpected dup() error */
}

/* Atomically duplicate 'oldfd' on 'newfd' */

if (dup2(oldfd, newfd) == -1) {
    /* Handle dup2() error */
}

/* Now check for close() errors on the file originally
   referred to by 'newfd' */

if (tmpfd != -1) {
    if (close(tmpfd) == -1) {
        /* Handle errors from close */
    }
}

另外参见

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

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/