dup2 / dup – 为什么我需要复制文件描述符?
我想了解使用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
的例子,我将不胜感激。
谢谢
dup系统调用复制一个现有的文件描述符,返回一个引用同一个底层I / O对象的新文件描述符。
Dup允许shell执行像这样的命令:
ls existing-file non-existing-file > tmp1 2>&1
2>&1告诉shell给命令一个描述符1的副本的文件描述符2(即stderr&stdout指向相同的fd)。
现在在tmp1文件中显示调用ls在不存在的文件上的错误信息和现有文件上的ls的正确输出。
下面的示例代码运行程序wc,将标准input连接到pipe道的读取端。
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 ie 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上,closuresp中的文件描述符,然后执行wc。 当wc从标准input读取时,它从pipe道读取。
这是如何使用dup来实现pipe道,以及现在使用pipe道来构build别的东西,这就是系统调用的美妙之处,你使用已经存在的工具来build立一个又一个的东西,这些工具是用别的等等。最后,系统调用是你在内核中获得的最基本的工具
干杯:)
复制文件描述符的另一个原因是与fdopen
一起fdopen
。 fclose
closures传递给fdopen
,所以如果你不想让原来的文件描述符closures,你必须先用dup
复制它。
请注意有关dup / dup2的一些要点
dup / dup2 – 从技术上讲,目的是通过不同的句柄在一个进程内共享一个File table Entry。 (如果我们分叉描述符在subprocess中被默认复制,并且文件表项也被共享)。
这意味着对于使用dup / dup2函数的单个打开文件表项,我们可以有多个文件描述符可能具有不同的属性 。
(尽pipe目前只有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值beteen dup2和fcntl close之后fcntl可能会引起竞争条件,因为涉及两个函数调用。
详情可以从http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html查看;
使用示例 –
在shell中实现作业控制的一个有趣的例子,在下面的链接中可以看到dup / dup2的使用
http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs
dup用来redirect进程的输出。
例如,如果要保存某个进程的输出,则复制输出(fd = 1),将重复的fdredirect到一个文件,然后分叉并执行该进程,并在进程结束时再次redirect保存fd输出。