92

我试图了解dup2and的用法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

谢谢

4

4 回答 4

50

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 上,关闭 p 中的文件描述符,然后执行 wc。当 wc 从其标准输入中读取时,它从管道中读取。
这就是使用 dup 实现管道的方式,现在使用 dup 的一种用途是使用管道构建其他东西,这就是系统调用的美妙之处,您使用已经存在的工具构建一个接一个的东西,这些工具又是使用构建的其他的等等..最后,系统调用是你在内核中获得的最基本的工具

干杯:)

于 2012-07-24T17:20:56.737 回答
19

复制文件描述符的另一个原因是将其与fdopen. fclose关闭传递给 的文件描述符fdopen,因此如果您不希望关闭原始文件描述符,则必须先复制它dup

于 2012-07-24T17:53:09.897 回答
4

dup 用于能够重定向进程的输出。

例如,如果要保存进程的输出,则复制输出 (fd=1),将复制的 fd 重定向到文件,然后 fork 并执行进程,当进程完成时,再次重定向保存 fd 到输出。

于 2012-07-24T16:27:53.257 回答
4

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 值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

于 2012-07-24T19:01:43.007 回答