【Linux】重定向函数dup/dup2

有时我们希望把标准输入重定向到一个文件,或者把标准输出重定向到一个网络连接。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版权协议,转载请附上原文出处链接和本声明。