一、dup/dup2
有时我们希望把标准输入重定向到一个文件,或者把标准输出重定向到一个网络连接。系统调用dup和dup2能够复制文件描述符。dup返回新的文件文件描述符(没有用的文件描述符最小的编号)。
dup2可以让用户指定返回的文件描述符的值,如果需要,则首先接近newfd的值,他通常用来重新打开或者重定向一个文件描述符。
1、dup函数
dup函数创建一个新的文件描述符,该新文件描述符和原有文件描述符oldfd指向相同的文件、管道或者网络连接。并且dup返回的文件描述符总是取系统当前可用的最小整数值。
dup和dup2失败时返回-1并设置errno。
#include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<string.h> #include<stdlib.h>int main() {//打开一个文件int fd = open("./test", 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; }
2、dup2函数
通过 oldfd 复制出一个新的文件描述符 newfd,如果成功,newfd 和函数返回值是同一个返回值,最终 oldfd 和新的文件描述符 newfd 都指向同一个文件。
oldfd: 需要复制的文件描述符
newfd: 新的文件描述符,这个描述符可以人为指定一个合法数字(0-1023),如果指定的数字已经被占用(和某个文件有关联),此函数会自动关闭 close() 断开这个数字和某个文件的关联,再来使用这个合法数字。
返回值:
成功:返回 newfd
失败:返回 -1
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> #include <unistd.h>static void usage(const char* proc) {printf("Usage:%s[server_ip][server_port]\n",proc); } int main(int argc,char *argv[]) {if(argc != 3){usage(argv[0]);return 1;}int sock = socket(AF_INET,SOCK_STREAM,0);if(sock<0){perror("socket");return 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]);int ret = connect(sock,(struct sockaddr*)&peer,sizeof(peer));if(ret<0){perror("connect");printf("%s\n",strerror(ret));return 3;}int dup = dup2(sock,1);//将标准输出重定向至sockchar buf[1024];while(1){printf("Please enter:");fflush(stdout);ssize_t s=read(0,buf,sizeof(buf));if(s<0){perror("read");return 4;}buf[s-1]=0;if(strncmp("quit",buf,4) == 0)break;printf("%s",buf);//往sock中写入消息fflush(stdout);}ssize_t _s = read(sock,buf,sizeof(buf));close(dup);close(sock);printf("sock:%s",buf);return 0; }