实际的例子使用dup或dup2
-
19-09-2019 - |
题
解决方案
一个实例的使用是I / O重定向。为此,您fork一个子进程,并关闭标准输入和标准输出文件描述符(0和1),然后你做你选择的另一个文件描述符现在将映射到最低的文件描述符,这是在这个DUP()情况下为0或1。
现在使用这个你可以Exec的任何一个孩子的过程,可能是不知道你的应用程序中,每当孩子写在标准输出(或从标准输入,无论你配置读取)的数据被写入所提供的文件描述符来代替。
壳使用此来实现与管道,例如命令由一个进程的标准输出连接到其他的标准输入/bin/ls | more
。
其他提示
最好的情况了解dup和dup2是重新定向。
第一件事情,我们需要知道的是,该系统有3默认文件id(或变量表示的输出或输入来源),有的输入和输出。他们 stdin
, stdout
, stderr
, 在整数,他们是 0
,1
,2
.大多数职能喜欢 fprintf
或 cout
直接的输出来 stdout
.
如果我们想要重新定向的输出,一种方式是得到,例如, fprintf
功能更多的参数指示 in
和 out
.
然而,有一个更优雅的方式:我们可以复盖默认文件的标识,以使他们指向的文件中,我们希望接收的输出。 dup
和 dup2
正是在这种情况。
让我们开始一个简单的例子:假设我们要重新定向的输出 fprintf
一txt文件命名为"chinaisbetter.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:
这就给出了一个直观的解释,可能需要检查平或详细的信息。实际上,我们说"拷贝"在这里,他们不是复制一切。
该文件id在这里是参照处理程序的文件。该文件描述上面提到的是一个结构体的记录文件的信息。
当您想了解POSIX功能,尤其是那些看似重复自己,这通常是好到的检查标准本身。在底部,您通常会看到两者的例子,以及推理执行背后(与存在)。
在这种情况下:
以下各节的信息容量。
实施例
重定向标准输出到文件
下面的示例关闭标准输出为当前处理,重新分配标准输出去由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标准1003.1-2001的主要是由于历史的原因,因为许多现有的应用程序中使用它们。
虽然所示的简短代码段是非常相似的行为,以dup2()
,基于该卷IEEE标准1003.1-2001的定义的其他功能的一致性实现是显著更加复杂。至少明显的是,可以步骤和分配或释放文件描述符之间被调用的信号捕获函数的可能影响。这可以通过阻塞信号来避免。
,因为它呈现由dup2()
以类型不安全版本提供的功能的类型安全版本fcntl()
功能没有被标记过时。它是在POSIX阿达结合使用。
在dup2()
功能并不意在关键区域使用作为同步机制。
在的[EBADF]的说明中,菲尔德斯超出范围的情况下,通过不是有效的法尔兹的给定情况下所覆盖。对于fildes
和fildes2
的描述是不同的,因为唯一的一种无效的是相关的fildes2
是,它是否超出范围;也就是说,它并不重要fildes2
是否是指当dup2()
呼叫由一个打开的文件。
未来路线
无。
参见
close()
,fcntl()
,open()
,IEEE标准1003.1-2001的基本定义体积,<unistd.h>
更改历史记录
首先,在第1期从SVID的问题1源性释放。
的一个实际例子是重定向消息输出到像一些日志文件一些其他流。下面是I / O重定向一个示例代码。结果 请参考这里原帖
#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()");
}
I /在壳O重定向最有可能被使用DUP2 / fcnlt系统调用来实现。
我们可以使用DUP2函数容易模仿重定向的$program 2>&1 > logfile.log
类型。
下面的程序重定向标准输出和stderr .i.e使用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