Linux Cdup和dup2函数详解

    科技2022-08-31  147

     

    一、dup函数介绍

          系统调用dup()创建文件描述符oldfd的一个副本,使用编号最低的未使用描述符作为新描述符。

          成功返回后,新旧文件描述符可以互换使用。它们引用相同的打开文件描述,因此共享文件偏移量和文件状态标志;

          例如,如果在其中一个描述符上使用lseek(2)修改文件偏移量,则另一个描述符的偏移量也会更改。

          这两个描述符不共享文件描述符标志(exec关闭标志)。重复描述符的close on exec标志(FD_CLOEXEC;

          请参见fcntl(2))已关闭。

    二、头文件和函数定义

    #include <unistd.h> int dup(int oldfd);

     代码示例:

       

    #include<stdio.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #define MAX_BUF_LEN 1024 int main() { int oldfd = open("tmp.txt", O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); if(oldfd < 0) { printf("Open failed!\n"); return -1; } int fd2 = dup(oldfd); if(fd2 < 0 ) { close(oldfd); printf("dup() failed!\n"); return -1; } char buf[MAX_BUF_LEN]; int bytes; /* 将标准输入写入buf,这里的0表示的是标准输入描述符,<unistd.h> 定义是 STDIN_FILENO */ while((bytes = read(0, buf, MAX_BUF_LEN - 1)) > 0) { if (buf[0] == 'q') { break; } printf("read bytes = %d\n", bytes); /* 将buf中数据写入fd2,实际写入oldfd */ if(write(fd2, buf, bytes) < bytes) { printf("Write failed!\n"); return 0; } memset(buf, 0, MAX_BUF_LEN); } if (close(fd2) != 0) { printf("close fd2 error!\n"); } if (close(oldfd) != 0) { printf("close oldfd error!\n"); } return 0; }

    三.dup2函数介绍

            dup2()系统调用执行与dup()相同的任务,但它不使用编号最低的未使用文件描述符,而是使用newfd中指定的描述符编号。如果描述符newfd以前是打开的,那么它在被重用之前是静默关闭的。

    关闭和重用文件描述符newfd的步骤是以原子方式执行的。这一点很重要,因为尝试使用close(2)和dup()实现等效功能会受到竞争条件的影响,因此newfd可能会在两个步骤之间重用。这种重用可能是因为主程序被分配文件描述符的信号处理程序中断,或者是因为并行线程分配了文件描述符。

    注意以下几点:

    如果oldfd不是有效的文件描述符,则调用失败,newfd未关闭。如果oldfd是有效的文件描述符,并且newfd的值与oldfd相同,那么dup2()不执行任何操作,并返回newfd。

    代码示例:

    #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <stdio.h> int main() { int oldfd; int fd; char *buf; if((oldfd = open("ifconfig.txt", O_RDWR | O_CREAT, 0644)) == -1) { printf("open error\n"); exit(-1); } fd = dup2(oldfd, fileno(stdout)); if(fd == -1) { printf("dup2 error\n"); return -1; } system("ifconfig"); if (close(oldfd) != 0) { printf("close oldfd error!\n"); return -1; } if (close(fd) != 0) { printf("close fd error!\n"); return -1; } return 0; }

      system函数执行过程中,将标准输出重定向到oldfd中,程序执行完会生成ifconfig.txt文件,内容如下:

      

    Processed: 0.023, SQL: 9