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

70gysomp  于 2023-02-07  发布在  其他
关注(0)|答案(4)|浏览(231)

我正在尝试理解dup2dup的用法。
在手册页中:

描述

dupdup2创建文件描述符oldfd的副本,成功返回dupdup2后,新旧描述符可以互换使用,它们共享锁、文件位置指针和标志;例如,如果通过在描述符之一上使用lseek来修改文件位置,则对于另一个描述符,位置也改变。
这两个描述符不共享close-on-exec标志,但是,dup将编号最小的未使用描述符用作新描述符。
dup2使newfd成为oldfd的副本,如有必要,先关闭newfd

返回值

dupdup2返回新的描述符,如果发生错误,则返回-1(在这种情况下,errno被适当地设置)。
为什么我需要那个系统调用?复制文件描述符有什么用?如果我有文件描述符,为什么我要复制它?如果你能解释并给我一个需要dup2/dup的例子,我会很感激。

p4tfgftt

p4tfgftt1#

dup系统调用复制一个现有的文件描述符,返回一个引用同一底层I/O对象的新文件描述符。
Dup允许shell实现如下命令:

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

2〉&1告诉shell给予命令一个文件描述符2,它是描述符1的副本(例如stderr和stdout指向相同的fd)。
现在,在 * non-existing file* 上调用 ls 的错误消息和在 existing file 上调用 ls 的正确输出显示在 * tmp 1 * 文件中。
下面的示例代码运行程序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]);
}

子进程将read end复制到文件描述符0上,关闭p中的文件描述符,并执行wc。当wc从其标准输入读取时,它从管道读取。
这就是使用dup实现管道的方式,现在使用dup可以构建其他东西,这就是系统调用的美妙之处,您可以使用已有的工具构建一个又一个东西,这些工具反过来又是使用其他东西构建的,依此类推。最后,系统调用是您在内核中获得的最基本的工具
干杯:)

r1zk6ea1

r1zk6ea12#

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

bjp0bcyl

bjp0bcyl3#

dup用于能够重定向来自进程的输出。
例如,如果您想保存一个进程的输出,您可以复制该输出(fd=1),将复制的fd重定向到一个文件,然后派生并执行该进程,当该进程完成时,再次将保存的fd重定向到输出。

wmomyfyw

wmomyfyw4#

请注意与dup/dup 2相关的一些要点
dup/dup 2-从技术上讲,其目的是通过不同的句柄在单个进程内共享一个文件表条目。(如果我们正在派生,则描述符默认在子进程中复制,并且文件表条目也被共享)。
这意味着我们可以使用dup/dup 2函数为一个打开文件表条目创建多个具有 * 可能不同属性 * 的文件描述符。
(尽管目前似乎只有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);

区别是(最后一个)-除了dup 2和fcntl之间的一些errno值之外,close后面跟fcntl可能会引发争用条件,因为涉及到两个函数调用。
可从http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html查看详细信息

使用示例-

在shell中实现作业控制时,有一个有趣的示例,其中可以看到dup/dup 2的使用。请参见下面的链接
http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

相关问题