dup2()是dup()的“升级版“,原型是int dup2(int oldfd, int newfd),作用是让文件描述符newfd与oldfd所关联的文件(或缓冲区或管道或共享内存等)关联起来,如果一开始newfd已经和某个文件关联了(一个描述符同一时刻只能关联一个文件),那它会先解除newfd和某个文件的关联,然后再关联oldfd关联的那个文件。下面就拿文件描述符0,1做参数来写两个例子。
我们知道,当程序一执行,系统默认为该进程分别分配有一块空间作为标准输入缓冲区、标准输出缓冲区和标准错误输出缓冲区,默认与它们关联的文件描述符分别是0,1,2,程序中各种涉及到缓冲区的操作其实本质上也是通过它们的文件描述来的。
demo1:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd=open("./1.txt",O_RDWR|O_CREAT,0644);
if(fd<0)
{
perror("open the 1.txt");
goto err0;
}
int ret=dup2(fd, 1); // 让本来指向标准输出缓冲区的描述符1指向文件1.txt
if(ret<0)
{
perror("dup2");
goto err1;
}
printf("where am I?\n"); //向输出缓冲区写入数据
close(fd);
return 0;
err1:
close(fd);
err0:
return 1;
}
上面程序中,先通过open()打开文件1.txt,得到与之关联的文件描述符fd,然后通过dop2()让本来关联着标准输出缓冲区的文件描述符0去关联文件1.txt,结果后面调用printf()向输出缓冲区写入内容时,它把1.txt误当做了输出缓冲区,于是语句“where am I?”被输出到了1.txt文件中:
demo2:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd=open("./1.txt",O_RDWR|O_CREAT,0644);
if(fd<0)
{
perror("open the 1.txt");
goto err0;
}
int ret=dup2(fd, 0); // 让本来指向标准入缓冲区的描述符0指向文件1.txt
if(ret<0)
{
perror("dup2");
goto err1;
}
char buf[128]="";
gets(buf); // 从输入缓冲区读取数据
puts(buf);
close(fd);
return 0;
err1:
close(fd);
err0:
return 1;
}
同理,上面的程序中,让本来关联着标准输入缓冲区的文件描述符0现在关联文件1.txt(文件中只有“where am I?”这一句话),当调用gets()从想输入缓冲区读取数据时,依然把文件1.txt当做了标准输入缓冲区,读取了文件中的“where am I?”并返回,所以终端也并没有给用户输入数据的机会: