Linux dup2 / dup - 为什么我需要复制文件描述符?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11635219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 13:53:49  来源:igfitidea点击:

dup2 / dup - why would I need to duplicate a file descriptor?

clinuxoperating-systemsystem-calls

提问by JAN

I'm trying to understand the use of dup2and dup.

我正在尝试了解dup2and的用法dup

From the man page :

从手册页:

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).  

Why would I need that system call? what is the use of duplicating the file descriptor?

为什么我需要那个系统调用?复制文件描述符有什么用?

If I have the file descriptor, why would I want to make a copy of it?

如果我有文件描述符,我为什么要复制它?

I'd appreciate if you could explain and give me an example where dup2/ dupis needed.

如果您能解释并给我一个需要dup2/的例子,我将不胜感激dup

Thanks

谢谢

采纳答案by Deepthought

The dup system call duplicates an existing file descriptor, returning a new one that refers to the same underlying I/O object.

dup 系统调用复制一个现有的文件描述符,返回一个引用相同底层 I/O 对象的新文件描述符。

Dup allows shells to implement commands like this:

Dup 允许 shell 执行这样的命令:

ls existing-file non-existing-file > tmp1  2>&1

The 2>&1 tells the shell to give the command a file descriptor 2 that is a duplicate of descriptor 1. (i.e stderr & stdout point to same fd).
Now the error message for calling lson non-existing fileand the correct output of lson existing fileshow up in tmp1file.

2>&1 告诉shell 给命令一个文件描述符2,它是描述符1 的副本。(即stderr 和stdout 指向同一个fd)。
现在,调用错误消息LS不存在的文件和正确的输出LS现有的文件中显示出来TMP1文件。

The following example code runs the program wc with standard input connected to the read end of a pipe.

以下示例代码运行程序 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]);
}

The child dups the read end onto file descriptor 0, closes the file de scriptors in p, and execs wc. When wc reads from its standard input, it reads from the pipe.
This is how pipes are implemented using dup, well that one use of dup now you use pipe to build something else, that's the beauty of system calls,you build one thing after another using tools which are already there , these tool were inturn built using something else so on .. At the end system calls are the most basic tools you get in kernel

子进程将读取端复制到文件描述符 0,关闭 p 中的文件描述符,然后执行 wc。当 wc 从其标准输入读取时,它从管道读取。
这就是使用 dup 实现管道的方式,好吧,使用 dup 的一种用法现在您使用管道来构建其他东西,这就是系统调用的美妙之处,您使用已经存在的工具构建一个又一个的东西,这些工具反过来构建使用其他诸如此类.. 最后,系统调用是您在内核中获得的最基本的工具

Cheers :)

干杯:)

回答by alinsoar

dup is used to be able to redirect the output from a process.

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

For example, if you want to save the output from a process, you duplicate the output (fd=1), you redirect the duplicated fd to a file, then fork and execute the process, and when the process finishes, you redirect again the saved fd to output.

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

回答by R.. GitHub STOP HELPING ICE

Another reason for duplicating a file descriptor is using it with fdopen. fclosecloses the file descriptor that was passed to fdopen, so if you don't want the original file descriptor to be closed, you have to duplicate it with dupfirst.

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

回答by Tanmoy Bandyopadhyay

Some points related to dup/dup2 can be noted please

请注意与 dup/dup2 相关的一些要点

dup/dup2 - Technically the purpose is to share one File table Entry inside a single processby different handles. ( If we are forking the descriptor is duplicated by default in the child process and the file table entry is also shared).

dup/dup2 - 从技术上讲,目的是通过不同的句柄在单个进程内共享一个文件表条目。(如果我们分叉描述符在子进程中默认是重复的并且文件表条目也是共享的)。

That means we can have more than one file descriptor having possibly different attributesfor one single open file table entry using dup/dup2 function.

这意味着我们可以使用 dup/dup2 函数为一个打开的文件表条目拥有多个具有不同属性的文件描述符。

(Though seems currently only FD_CLOEXEC flag is the only attribute for a file descriptor).

(虽然目前似乎只有 FD_CLOEXEC 标志是文件描述符的唯一属性)。

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

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);

Differences are (for the last)- Apart from some errno value beteen dup2 and fcntl close followed by fcntl may raise race conditions since two function calls are involved.

差异是(最后一个)- 除了 dup2 和 fcntl 之间的一些 errno 值,关闭后跟 fcntl 可能会引发竞争条件,因为涉及两个函数调用。

Details can be checked from http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html

详情可从http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html查看

An Example of use-

使用示例-

One interesting example while implementing job control in a shell, where the use of dup/dup2 can be seen ..in the link below

在 shell 中实现作业控制时的一个有趣示例,在下面的链接中可以看到 dup/dup2 的使用

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs