您的位置:首页 > 运维架构 > Linux

Linux-dup和dup2函数

2015-02-12 16:37 274 查看
dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符。它们经常用来重定向进程的stdin、stdout和stderr。这两个函数的原形如下:

#include <unistd.h>

int dup( int oldfd );

int dup2( int oldfd, int targetfd );

1. 文件描述符在内核中数据结构

在具体说dup/dup2之前, 我认为有必要先了解一下文件描述符在内核中的形态。

一个进程在此存在期间,会有一些文件被打开,从而会返回一些文件描述符,从shell

中运行一个进程,默认会有3个文件描述符存在(0、1、2), 0与进程的标准输入相关联,

1与进程的标准输出相关联,2与进程的标准错误输出相关联,一个进程当前有哪些打开

的文件描述符可以通过/proc/进程ID/fd目录查看。 下图可以清楚的说明问题:

  进程表项

————————————————

   fd标志 文件指针

_____________________

fd 0:|________|____________|————> 文件表

fd 1:|________|____________|

fd 2:|________|____________|

fd 3:|________|____________|

| ……. |

|_____________________|

图1

       

文件表中包含:文件状态标志、当前文件偏移量、v节点指针,这些不是本文讨论的

重点,我们只需要知道每个打开的文件描述符(fd标志)在进程表中都有自己的文件表

项,由文件指针指向。

2. dup/dup2函数

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

#include <unistd.h>

int dup(int oldfd);

int dup2(int oldfd, int newfd);

从图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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: