C语言 dup2 / dup - 为什么我需要复制文件描述符



我试图理解dup2dup的用法。

从手册页:

描述

dupdup2 创建文件描述符的副本 oldfd 。成功返回dupdup2后,新旧描述符可以互换使用。它们共享锁、文件位置指针和标志;例如,如果通过对其中一个描述符使用 lseek 修改文件位置,则另一个描述符的位置也会更改。

但是,这两个描述符不共享 close-on-exec 标志。 dup对新描述符使用编号最低的未使用描述符。

dup2使newfd成为oldfd的副本,必要时首先关闭newfd

返回值

dupdup2 返回新的描述符,如果发生错误,则返回 -1(在这种情况下,errno设置正确(。

为什么需要该系统调用?复制文件描述符有什么用?如果我有文件描述符,我为什么要复制它?如果您能解释并给我一个例子,我将不胜感激,需要dup2/dup

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 worldn", 12);
    close(p[STDIN]);
    close(p[STDOUT]);
}

子将读取端 dup 到文件描述符 0 上,关闭文件 deP中的脚本和WC中的执行者。当 wc 从其标准输入读取时,它会从管。
这就是使用 dup 实现管道的方式,那么现在 dup 的一个用途你使用管道来构建其他东西,这就是系统调用的美妙之处,你使用已经存在的工具构建一个又一个的东西,这些工具反过来使用其他东西构建等等。最后,系统调用是你在内核中获得的最基本的工具

干杯:)

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

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

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

与 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关闭后跟 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

最新更新