我试图了解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
的示例,我将不胜感激。
由于
答案 0 :(得分:39)
dup系统调用复制现有的文件描述符,返回一个新的文件描述符 指的是相同的底层I / O对象。
Dup允许shell实现如下命令:
ls existing-file non-existing-file > tmp1 2>&1
2>& 1告诉shell给命令一个文件描述符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,关闭文件de
p中的脚本和exec wc。当wc从其标准输入读取时,它从中读取
管道。
这就是使用dup实现管道的方法,以及现在你使用管道来构建其他东西,这就是系统调用的美妙之处,你使用已经存在的工具构建一个接一个的东西,这些工具是使用工具构建的别的东西......
最后,系统调用是您在内核中获得的最基本的工具
干杯:)
答案 1 :(得分:16)
复制文件描述符的另一个原因是将其与fdopen
一起使用。 fclose
关闭传递给fdopen
的文件描述符,因此如果您不希望关闭原始文件描述符,则必须先使用dup
复制它。
答案 2 :(得分:5)
请注意与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);
差异(最后) - 除了一些错误值beteen dup2和fcntl 由于涉及两个函数调用,因此关闭后跟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
答案 3 :(得分:4)
dup用于能够重定向进程的输出。
例如,如果要保存进程的输出,则复制输出(fd = 1),将重复的fd重定向到文件,然后fork并执行该进程,当进程完成时,再次将保存的fd重定向到输出。