基础IO 七

86 阅读1分钟

“我正在参加「掘金·启航计划」”

一、dup2

✔ 测试用例一:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

//输出重定向
int main01()
{
    int fd = open("log.txt", O_WRONLY|O_CREAT, 0644);
    if(fd < 0)
    {
        perror("open");
        return 1;
    }

    dup2(fd, 1);//此时再写入就不是标准输出,而是fd                             
    const char* msg = "hello dup2->output\n";
    int i = 0;
    while(i < 5)
    {
        write(1, msg, strlen(msg));
        i++;
    }

    close(fd);

    return 0;
}

//输入重定向
int main02()
{
    int fd = open("log.txt", O_RDONLY);
    if(fd < 0)
    {
        perror("open");
        return 1;
    }

    dup2(fd, 0);//此时再读就不是从标准输入读,而是fd
    char buffer[1024];
    ssize_t sz = read(0, buffer, sizeof(buffer) - 1);
    if(sz > 0)                                       
    {
        buffer[sz] = 0;
        printf("%s", buffer);
    }

    close(fd);

    return 0;
}

//追加重定向  
int main03()
{
    int fd = open("log.txt", O_WRONLY|O_APPEND);
    if(fd < 0)
    {
        perror("open");
        return 1;
    }

    dup2(fd, 1);//此时再写入就不是标准输出,而是fd
    const char* msg = "hello dup2->append\n";
    int i = 0;
    while(i < 5)
    {
        write(1, msg, strlen(msg));
        i++;
    }                                            

    close(fd);

    return 0;                                    
}                                                
  • 我们之前自己实现重定向时是先 close 被重定向的文件,再 open 想重定向的文件。有没有可以不 close 被重定向的文件,直接重定向,此时系统提供了类似的接口 dup2 来解决 close 多此一举的行为。

  • 使用 dup2,需要包含 unistd 头文件,

    在这里插入图片描述

    要输出的文件描述符是 1,而要重定向的目标文件描述符是 fd(echo "hello" > log.txt),dup2 应该怎么传参 —— dup2(1, fd) || dup2(fd, 1) ❓

    很明显,依靠函数原型,我们就能认为 dup2(1, fd),因为 1 是先打开的,而 fd 是后打开的,可实际上并不是这样的。文档中说 newfd 是 oldfd 的一份拷贝,这里拷贝的是文件描述符对应数组下标的内容,所以数组内容,最终应该和 oldfd 一致。换言之,这里就是想把 1,不要指向显示器了,而指向 log.txt,fd 也指向 log.txt。所以这里的 oldfd 对应 fd,newfd 对应 1,所以应该是 dup2(fd, 1)。

  • 运行结果

    ==输出重定向==

    在这里插入图片描述

    ==输入重定向==

    在这里插入图片描述

    ==追加重定向==

    在这里插入图片描述

  • 所以现在我们就明白了:

    echo "hello world" > log.txt —— echo 是一个进程;"hello world" 默认是调用 printf 或 write 往显示器上输出;log.txt 是调用 open 使用 O_WRONLY|O_CREAT 打开;> 是调用 dup2,将默认标准输出 1 的内容改为 log.txt;

    在这里插入图片描述

    < 就是 dup2(fd, 0),且 open 文件的方式是 O_RDONLY;

    在这里插入图片描述

    >> 同 >,都是 dup2(fd, 1),只不过它打开文件的方式是 O_WRONLY|O_APPEND;

    在这里插入图片描述

  • 进程替换时,是否会干扰重定向对应的数据结构 ❓

    在这里插入图片描述

    换言之,将来 fork,创建子进程,子进程会以父进程的大部分数据为模板,子进程进行程序替换时,并不会影响曾经打开的文件,也就不会影响重定向对应的数据结构。