有时我们希望把标准输入重定向到一个文件,或者把标准输出重定向到一个网络连接。dup()与dup2()能对输入文件描述符进行重定向。
函数描述
函数声明
返回值:
可能有点绕,解释一下
dup和dup2函数都是调用是文件描述符oldfd的副本(新创建的)。
dup函数:dup()使用最小的未使用的描述符来描述新的描述符
dup函数测试:以输出重定向为例
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
int main()
{
//打开一个文件
int fd = open("./log", O_CREAT | O_RDWR, 0666);
if(fd <0)
{
perror("open");
return 1;
}
//1、关闭标准输出文件描述符
close(1);
//2、进行重定向:使用最小未被使用的1来替代fd,即new_fd值是1,其文件指向fd
int new_fd = dup(fd);
if(new_fd < 0)
{
perror("dup");
return 2;
}
close(fd);//关闭不用的文件描述符,
char buf[1024];
while(1)
{
memset(buf,'\0',sizeof(buf));
ssize_t s = read(0,buf,sizeof(buf)-1);
if(s > 0)
{
buf[s -1] = 0;
}
if(strncmp("quit",buf,4) == 0)
break;
printf("%s\n",buf);
fflush(stdout);//刷新,由行缓存变成了全缓冲
}
close(new_fd);
return 0;
}测试结果:
dup2函数:dup2()使newfd成为oldfd的副本,如果需要,则首先关闭newfd,有两种情况不会关闭之前的newfd;
(1)oldfd不是一个有效的文件描述符,dup函数调用失败,
(2)oldfd是一个有效的文件描述符,但是newfd和oldfd相等,函数什么也不做,返回newfd。
dup2函数测试:以标准输出重定向为例
只要将dup函数使用替换从dup2,其他一样
//close(1);dup2函数内部已经关闭了newfd 1
//2、进行重定向:将oldfd(fd)的一份拷贝给了newfd(1),返回的是新的newfd 即1
int new_fd = dup2(fd,1);
if(new_fd < 0)
{
perror("dup");
return 2;
}
close(fd);//关闭不用的文件描述符,使用dup2实现的客户端
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
//使用dup2将客户端1号描述符重定向到sock文件描述符
//即:将标准输出的内容直接写道sock
int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("%s [ip] [port]\n",argv[0]);
exit(1);
}
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0)
{
perror("socket");
exit(2);
}
struct sockaddr_in peer;
peer.sin_family = AF_INET;
peer.sin_port = htons(atoi(argv[2]));
peer.sin_addr.s_addr = inet_addr(argv[1]);
// 2 connect
if(connect(sock,(struct sockaddr*)&peer,sizeof(peer)) < 0)
{
perror("connect");
exit(3);
}
printf("connect success\n");
close(1);
int dup = dup2(sock,1);//将1文件描述符关闭,1重定向到sock
close(sock);
char buf[1024];
while(1)
{
ssize_t s = read(0,buf,sizeof(buf)-1);
if(s >0)
{
buf[s -1]= 0;
}
if(strncmp("quit",buf,4) == 0)
break;
printf("%s",buf);//将sock中写信息,
fflush(stdout);//必须进行刷新,printf由行缓冲变成全缓冲
sleep(1);
}
close(dup);
return 0;
}版权声明:本文为wenqiang1208原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。