dup,dup2,dup3 --duplicate a file descriptor 复制一个文件描述符
大纲
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd , int newfd);
int dup3(int oldfd , int newfd , int flags);
描述:
这些系统调用 创建了一个原始文件描述符的复本.
dup() 为新复制的文件描述符使用一个未用的最小数字
dup2() 复制原先的文件描述符 到一个新的文件描述符上.如果有必要将关闭新的描述符所映射的打开文件.但是请注意下面:
①如果旧的文件描述符不是一个有效的文件描述符,系统调用失败,新的文件描述符不会关闭.
②如果旧的文件描述符是一个有效的文件描述符,但是新的文件描述符和旧的文件描述符相同,dup2()不做任何事情
成功执行这些系统调用之后,新的文件描述符和旧的文件描述符就可以进行交换使用了.他们代表着相同的文件描述符,指向相同的打开文件,因此,他们共享该打开文件的
文件偏移量 和 文件状态标志.举个例子,如果文件偏移量被其中一个文件描述符使用lseek()修改了,那么另外一个文件描述符的文件偏移量也随之修改.
但是请注意:他们不共享(the close-on-exec flag)标志位. close-on-exec标志位在复制文件描述符时是关闭的.
(close-on-exec标志位的作用是:它属于该文件描述符的一个属性,表示子程序是否能够继承该文件描述符,如果标志位off,表示未设置,则子进程可以使用该文件描述符,on表示已设置,那么就不可使用.这里根据意思也很好理解.询问你是否在exec调用时close文件描述符,如果off,则可用,on则不可用--译者注).
dup3() 其实和dup2()相同,除了以下两点:
①.它能够设置close-on-exec 标志位的开启和关闭.它通过在flag参数位设置 O_CLOEXEC 来强行设置 close-on-exec 标志位的开启.这样子进程就不能够使用该文件描述符了.查看关于close-on-exec标志位的更多信息,请参看open(2),了解为什么该标志位是有用的.
②如果旧的文件描述符和新的文件描述符相同,dup3()调用失败,返回EINVAL 错误.
返回值:
成功调用之后,这些系统调用返回一个新的文件描述符, 如果错误,返回 -1,并且errno 错误类型将被合理的设置.
错误:
EBADF:旧的文件描述符不是一个打开的文件描述符或者新的文件描述符超出了文件描述符允许的范围时返回
EBUSY:(Linux only)当调用dup2()或者dup3()的时候, 系统正在运行open()或者 dup()时返回.
EINTR:dup2()或者 dup3()系统调用被信号打断时返回.
EINVAL: dup3() 标志位包含一个无效值,或者旧的文件描述符和新的文件描述符相同时返回.
EMFILE:当进程已经打开最大的文件描述符数字之后,尝试复制文件描述符时,无文件描述符数字可用时返回.
版本:
dup3()是在版本linux2.6.27增加的,glibc是从版本2.9增加的.
注意点:
dup2()在新的文件描述符超出文件描述符允许的范围时返回的错误是不同于fcntl(...,F_DUPFD,...).在一些系统上,dup2()返回的EINVAL和 F_DUPFD相同.
如果新的文件描述符是打开的,任何将在close()调用时报告的错误会丢失. 一个小心的程序员将会在调用 dup2()或者dup3()之前,关闭 新的文件描述符.