linux—dup和dup2重定向文件描述符

【dup】
利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一

个新的现有的最小的未被使用的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这两个描述符共享同一个数据结构,指的是文件描述符所用的数据结构相同,不是文件描述符相同。

代码如下:
linux—dup和dup2重定向文件描述符
        在此例中,dup之前,先关掉1号描述符,对应的是标准输出,所以dup后的new_dup就是1,1号文件描述符原来是标准输出,现在是./log,所以后面标准输出的helloworld 都被打印在./log 文件里了。
结果如下:
linux—dup和dup2重定向文件描述符
【dup2】
  dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id

。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的

第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一

个参数指向的文件。

代码如下:

linux—dup和dup2重定向文件描述符

结果如下:

linux—dup和dup2重定向文件描述符


【总结】

APUE和man文档都用一句话简明的说出了这两个函数的作用:复制一个现存的文件描述符。

#include <unistd.h>

int dup(int oldfd);

int dup2(int oldfd, int newfd);


进程表项
————————————————

   fd标志 文件指针
      _____________________
fd 0:|________|____________|------------> 文件表
fd 1:|________|____________|
fd 2:|________|____________|
fd 3:|________|____________|
     |     .......         |
     |_____________________|

                图1
       

从图1来分析这个过程,当调用dup函数时,内核在进程中创建一个新的文件描述符,此

描述符是当前可用文件描述符的最小数值,这个文件描述符指向oldfd所拥有的文件表项。


  进程表项
————————————————

   fd标志 文件指针
      _____________________
fd 0:|________|____________|                   ______
fd 1:|________|____________|----------------> |      |
fd 2:|________|____________|                  |文件表|
fd 3:|________|____________|----------------> |______|
     |     .......         |
     |_____________________|

                图2:调用dup后的示意图

如图2 所示,假如oldfd的值为1, 当前文件描述符的最小值为3, 那么新描述符3指向

描述符1所拥有的文件表项。

         dup2和dup的区别就是可以用newfd参数指定新描述符的数值,如果newfd已经打开,则

先将其关闭。如果newfd等于oldfd,则dup2返回newfd, 而不关闭它。dup2函数返回的新

文件描述符同样与参数oldfd共享同一文件表项。

APUE用另外一个种方法说明了这个问题:

实际上,调用dup(oldfd);

等效与
        fcntl(oldfd, F_DUPFD, 0)

而调用dup2(oldfd, newfd);

等效与
        close(oldfd);
        fcntl(oldfd, F_DUPFD, newfd);