文件描述符复制dup,dup2函数

写在前面

本文主要介绍 Linux系统编程中用于文件描述符复制的两个函数dup(),dup2()

函数功能

文件描述符不用再过多赘述,它是Linux系统编程中用来描述一个文件的东西,而dup()dup2() 是两个非常有用的系统调用,都是用来复制一个文件的描述符,使新的文件描述符也标识旧的文件描述符所标识的文件。

dup

作用:复制一个新的文件描述符
函数原型:int dup(int oldfd);

头文件:

  • #include <unistd.h>

参数:

  • 旧的文件描述符

返回值

  • 成功:返回新的文件描述符,是调用进程文件描述符表中最小可用的文件描述符,最终 oldfd 和新的文件描述符都指向同一个文件。
  • 失败:返回 -1, 并设置 errno

举例

使用dup()函数复制一个文件描述符,同时对一个文件进行写操作

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

int main(int argc, char *argv[]){
    int fd1;
    fd1 = open("test.txt",O_RDWR|O_CREAT|O_TRUNC,0644);//打开一个文件
    if(fd1 == -1){
        perror("open error");
        exit(1);
    }   

    char *str1 = "hello fd1\n";
    write(fd1, str1, strlen(str1));//通过文件描述符fd1向文件中写

    char *str2 = "hello fd2\n";
    int fd2 = dup(fd1);
    write(fd2, str2, strlen(str2));//通过文件描述符fd2向文件中写
    
    close(fd1);//关闭文件描述符
    close(fd2);
    return 0;
}

程序执行结果,两个字符串都在test.txt内,dup() 复制的新文件描述符是系统自动分配的最小可用的文件描述符
image.png

dup2

作用:通过 oldfd 复制出一个新的文件描述符 newfd,如果成功,newfd 和函数返回值是同一个返回值,最终 oldfd 和新的文件描述符 newfd 都指向同一个文件。
函数原型:int dup2(int oldfd, int newfd);
头文件:

  • #include <unistd.h>

参数:

  • oldfd:旧的文件描述符
  • newfd:新的文件描述符

返回值:

  • 成功:返回新的文件描述符
  • 失败:返回-1, 设置errno

案例

将上述案例通过dup2()实现

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

int main(int argc, char *argv[]){
    int fd1;
    fd1 = open("test.txt",O_RDWR|O_CREAT|O_TRUNC,0644);
    if(fd1 == -1){
        perror("open error");
        exit(1);
    }
    printf("fd1========%d\n", fd1);
//先通过fd1复制出fd2,fd1,fd2都指向"test.txt"
//将fd2设置为标准输出(显示在屏幕上)
    int fd2 = dup2(fd1, STDOUT_FILENO);
//下面这句话不会出现在屏幕上,而是在"test.txt"中,
// printf()是标准库函数,最终还是会调用系统调用函数write()
// 相当于这样,write(test,),往 test 文件描述符写内容,
// 默认的情况下, test 文件描述符指向标准输出设备(如,显示屏)
// 所以, printf()的内容先显示到屏幕上
// 但是现在 test 文件描述符指向文件 "test.txt"
// 所以,printf()的内容会写入文件 "test.txt"
    printf("fd2========%d\n", fd2);
    close(fd1);
    close(fd2);
    return 0;
}

程序执行结果如下
image.png
一个出现在文件中, 一个出现在test.txt

区别

dup2dup区别是dup2可以用参数newfd指定新文件描述符的数值。若参数newfd已经被程序使用,则系统就会将newfd所指的文件关闭,若newfd等于oldfd,则返回newfd,而不关闭newfd所指的文件。dup2所复制的文件描述符与原来的文件描述符共享各种文件状态。共享所有的锁定,读写位置和各项权限或flags等.