实际例子使用dup或dup2

时间:2009-11-12 07:33:24

标签: c file unix system-calls dup

我知道dup / dup2做了什么,但我不知道何时会使用它。

任何实际例子?

感谢。

5 个答案:

答案 0 :(得分:59)

一个示例用法是I / O重定向。为此你分叉一个子进程并关闭stdin或stdout文件描述符(0和1)然后你在你选择的另一个filedescriptor上做一个dup(),它现在将被映射到最低的可用文件描述符,这是在这里案例0或1。

使用它你现在可以执行任何可能不知道你的应用程序的子进程,每当子进程写入stdout(或从stdin读取,无论你配置什么),数据都会被写在提供的文件描述符上。

Shells使用它来实现带管道的命令,例如/bin/ls | more通过将一个进程的stdout连接到另一个进程的stdin。

答案 1 :(得分:22)

了解dup和dup2的最佳方案是重定向 首先我们需要知道的是系统有3个默认文件id(或指示输出或输入源的变量)来处理输入和输出。它们为stdinstdoutstderr,整数为012。大多数功能(如fprintfcout)都会直接输出到stdout
如果我们想要重定向输出,可以给出一种方法,例如fprintf函数更多的参数表示inout
但是,有一种更优雅的方式:我们可以覆盖默认文件ID,使它们指向我们想要接收输出的文件。 dupdup2完全适用于这种情况 现在让我们从一个简单的示例开始:假设我们要将fprintf的输出重定向到名为" chinaisbetter.txt"的txt文件。首先我们需要打开这个文件

int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);

然后我们希望stdout指向" chinaisbetter.txt"通过使用dup函数:

dup2(fw,1);

现在stdout(1)指向" chinaisbetter.txt"的描述符即使它仍然是1,但输出现在被重定向。
然后您可以照常使用printf,但结果将显示在txt文件中,而不是直接显示在屏幕上:

printf("Are you kidding me? \n");

<强> PS

  1. 这只是一个直观的解释,您可能需要查看联机帮助页或详细信息。实际上,我们说&#34; copy&#34;在这里,他们并没有复制一切。

  2. 此处的文件ID指的是文件的处理程序。上面提到的文件描述符是记录文件信息的结构。

答案 2 :(得分:9)

当您对POSIX函数感到好奇时,特别是那些似乎自我复制的函数,对check the standard itself来说通常都很好。在底部,您通常会看到示例,以及两者的实现(和存在)背后的推理。

在这种情况下:

以下部分内容丰富。

实施例

将标准输出重定向到文件

以下示例关闭当前进程的标准输出,重新分配标准输出以转到pfd引用的文件,并关闭原始文件描述符以进行清理。

#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...

重定向错误消息

以下示例将邮件从stderr重定向到stdout

#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...

应用程序使用

无。

原理

dup()dup2()功能是多余的。他们的服务也由fcntl()功能提供。由于许多现有应用程序使用它们,因此它们已被包含在IEEE Std 1003.1-2001的这一卷中,主要是出于历史原因。

虽然显示的简短代码段与dup2()的行为非常相似,但基于本卷IEEE Std 1003.1-2001中定义的其他功能的一致性实现要复杂得多。最明显的是信号捕获函数的可能影响,可以在步骤之间调用并分配或释放文件描述符。这可以通过阻止信号来避免。

dup2()函数未标记为过时,因为它提供了由fcntl()在类型不安全版本中提供的类型安全版本的功能。它用于POSIX Ada绑定。

dup2()函数不适合在关键区域中用作同步机制。

在[EBADF]的描述中,fildes超出范围的情况由fildes无效的特定情况涵盖。 fildesfildes2的说明不同,因为与fildes2相关的唯一无效性是否超出范围;也就是说,在fildes2调用时,dup2()是否引用打开的文件并不重要。

未来方向

无。

另见

close()fcntl()open(),IEEE Std 1003.1-2001的基本定义卷,<unistd.h>

更改历史记录

首先在问题1中发布。源自SVID的问题1。

答案 3 :(得分:5)

一个实际的例子是将输出消息重定向到某些其他流,如某些日志文件。以下是I / O重定向的示例代码 请参阅原始帖子here

#include <stdio.h>

main()
{
    int    fd;
    fpos_t pos;

    printf("stdout, ");

    fflush(stdout);
    fgetpos(stdout, &pos);
    fd = dup(fileno(stdout));
    freopen("stdout.out", "w", stdout);

    f();

    fflush(stdout);
    dup2(fd, fileno(stdout));
    close(fd);
    clearerr(stdout);
    fsetpos(stdout, &pos);        /* for C9X */

    printf("stdout again\n");
}

f()
{
printf("stdout in f()");
}

答案 4 :(得分:0)

最有可能使用dup2 / fcnlt系统调用在外壳中实现I / O重定向。

我们可以使用dup2函数轻松模拟$program 2>&1 > logfile.log重定向类型。

下面的程序同时重定向stdout和stderr。即,使用dup2模拟$program 2>&1 > output的行为。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int
main(void){
    int close_this_fd;
    dup2(close_this_fd = open("output", O_WRONLY), 1);
    dup2(1,2);
    close(close_this_fd);
    fprintf(stdout, "standard output\n");
    fprintf(stderr, "standard error\n");
    fflush(stdout);
    sleep(100); //sleep to examine the filedes in /proc/pid/fd level.
    return;
}

vagrant@precise64:/vagrant/advC$ ./a.out
^Z
[2]+  Stopped                 ./a.out
vagrant@precise64:/vagrant/advC$ cat output
standard error
standard output
vagrant@precise64:/vagrant/advC$ ll /proc/2761/fd
total 0
dr-x------ 2 vagrant vagrant  0 Jun 20 22:07 ./
dr-xr-xr-x 8 vagrant vagrant  0 Jun 20 22:07 ../
lrwx------ 1 vagrant vagrant 64 Jun 20 22:07 0 -> /dev/pts/0
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 1 -> /vagrant/advC/output
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 2 -> /vagrant/advC/output