浅谈dup和dup2的用法

来源:互联网 发布:java反射调用静态方法 编辑:程序博客网 时间:2024/05/22 03:36

一、dup和dup2函数
这两个函数都可以来复制一个现有的文件描述符,他们的声明如下:

 #include <unistd.h> int  dup(int fd); int dup2(int fd, int fd 2);

关于dup函数,当我们调用它的时候,dup会返回一个新的描述符,这个描述一定是当前可用文件描述符中的最小值。我们知道,一般的0,1,2描述符分别被标准输入、输出、错误占用,所以在程序中如果close掉标准输出1后,调用dup函数,此时返回的描述符就是1。
对于dup2,可以用fd2指定新描述符的值,如果fd2本身已经打开了,则会先将其关闭。如果fd等于fd2,则返回fd2,并不关闭它。
这两个函数返回的描述符与fd描述符所指向的文件共享同一文件表项。如下图所示:
这里写图片描述
也就是fd与fd2可对同一个文件进行读写操作。且其是一种原子操作。
二、重定向示例
1. dup

  8 #include <stdio.h>  9 #include <unistd.h> 10 #include <stdlib.h> 11 #include <sys/stat.h> 12 #include <fcntl.h> 13  14 int main(int argc, char* argv[]) 15 { 16     int i_fd = open("hello.txt", O_CREAT|O_APPEND|O_RDWR, 0666); 17  18     if(i_fd < 0) 19     { 20         printf("open error!\n"); 21         return 0; 22     } 23  24     if(write(i_fd, "hello fd\n", 9) != 9) 25     { 26         printf("write fd error\n"); 27  28     } 29  30     int i_dup_fd = dup(i_fd); 31     if(i_dup_fd < 0) 32     { 33         printf("dup error!\n"); 34         return 0; 35     } 36  37     printf("i_dup_fd = %d \t i_fd = %d\n", i_dup_fd, i_fd); 38     close(i_fd); 39  40     char c_buffer[100]; 41     int n = 0; 42     while((n = read(STDIN_FILENO, c_buffer, 1000)) != 0) 43     { 44         if(write(i_dup_fd, c_buffer, n) != n) 45         { 46             printf("write dup fd error!\n"); 47             return 0; 48         } 49     } 50     return 0; 51 }

如上打开一个文件,我们先写入文件内容“hello fd”,然后将fd的描述符拷贝到dup_fd 的文件描述符上,然后将标准输入的内容写入到dup_fd 的文件中。
运行程序如下:
这里写图片描述
查看文件可以看到文件内容如下:
这里写图片描述

  1. dup2
    如下关于dup2的使用:
  8 #include <stdio.h>  9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 #include <sys/stat.h> 13 #include <fcntl.h> 14  15 int main(int argc, char* argv[]) 16 { 17     int i_fd = open("hello_dup2.txt", O_CREAT|O_APPEND|O_RDWR, 0666); 18  19  20     if(i_fd < 0) 21     { 22         printf("open error!\n"); 23         return 0; 24     } 25  26     if(write(i_fd, "hello i_fd\n", 11) != 11) 27     { 28         printf("write dup2 error\n"); 29     } 30  31  32     int i_dup2_fd = dup2(i_fd, STDOUT_FILENO); 33  34     if(i_dup2_fd != STDOUT_FILENO) 35     { 36         printf("error dup2!\n"); 37         return 0; 38     } 39     close(i_fd); 40  41     char c_buf[1024]; 42     int i_read_n = 0; 43     while((i_read_n = read(STDIN_FILENO, c_buf, 1024)) != 0) 44     { 45         i_read_n = read(STDIN_FILENO, c_buf + i_read_n, sizeof(c_buf) - 1 - i_read_n); 46  47         if(i_read_n < 0) 48         { 49             printf("read error!\n"); 50             return 0; 51         } 52  53         printf("%s", c_buf); 54         fflush(stdout); 55         sleep(1); 56     } 57     close(i_dup2_fd); 58  59     return 0; 60  61 }

如上,这里没有像使用dup的时候显示的调用write函数将标准输入的内容写入到指定文件中,而是将标准输出重定向到指定文件中,然后调用printf函数将标准输出的内容重定向到指定文件中。我们在写简单的日志时就可以将printf的内容重定向到日志中,使用printf作为写日志的接口。
如上运行程序如下:
这里写图片描述

查看hello_dup2.txt可以看到如下:
这里写图片描述