现在的位置: 首页 > 综合 > 正文

dup和dup2函数

2012年09月08日 ⁄ 综合 ⁄ 共 1548字 ⁄ 字号 评论关闭

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

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

一个进程在此存在期间,会有一些文件被打开,从而会返回一些文件描述符,从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
/dup
2函数

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

#include <unistd.h>

int dup
(int oldfd);

int dup
2(int oldfd, int newfd);

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

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

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

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

                图2:调用dup
后的示意图

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

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

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

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

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

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

实际上,调用dup
(oldfd);

等效与
        fcntl(oldfd, F_DUPFD, 0)

而调用dup
2(oldfd, newfd);

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

printf -> stdout -> STDOUT_FILENO(1) -> 终端(tty)

重拾终端输出方法

ttyfd = open("/dev/tty", O_RDWR);

dup
2(ttyfd, STDOUT_FILENO);

close(ttyfd);

抱歉!评论已关闭.