下面两个函数都可用来复制一个现存的文件描述符:

#include<unistd.h>
int dup(int filedes);
int dup2(int filedes,int filedes2);
两函数的返回值:若成功则返回新的文件描述符,若出错则返回-1

由dup返回的新文件描述符一定是当前可用文件描述符中的最小值。用dup2则可以用filedes2参数指定新描述符的数值。如果filedes2已经打开,则现将其关闭。如若filedes等于filedes2,则dup2返回filedes2,而不关闭它。

这些函数返回的新文件描述符与参数filedes共享同一文件表项。如图所示,我们假定执行了:

  newfd=dup(1);

当此函数开始执行时,假定下一个可用的描述符是3(这是非常可能的,因为0,1和2由shell打开)。因为两个描述符指向同一文件表项,所以它们共享同一文件状态标志(读、写、添加等)以及同一当前文件偏移量。

每个文件描述符都有它自己的一套文件描述符标志。

复制一个描述符的另一种方式是使用fcntl函数,实际上,可调用:

dup(filedes);

等效于

fcntl(filedes,F_DUPFD,0);

而调用

dup2(filedes,filedes2);

等效于

close(filedes2);

fcntl(filedes,F_DUPFD,filedes2);

在后一种情况下,dup2并不完全等效于close加上fcntl。它们之间的区别是:

1)dup2是一个原子操作,而close及fcntl则包括两个函数调用,有可能在close和fcntl之间插入执行信号捕获函数,它可能修改文件描述符。

2)dup2和fcntl有某些不同的errno。

重点解释两个地方:

  • 第3幅图,要执行dup2(fd, 1);,文件描述符1原本指向tty,现在要指向新的文件somefile,就把原来的关闭了,但是tty这个文件原本有两个引用计数,还有文件描述符save_fd也指向它,所以只是将引用计数减1,并不真的关闭文件。

  • 第5幅图,要执行dup2(save_fd, 1);,文件描述符1原本指向somefile,现在要指向新的文件tty,就把原来的关闭了,somefile原本只有一个引用计数,所以这次减到0,是真的关闭了。

1.dup()和dup2()函数格式如下:

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

dup() uses the lowest-numbered unused descriptor for the new descriptor.
    dup2() makes newfd be the copy of oldfd, closing newfd first ifnecessary, but note the following:
   *If oldfd is not a valid file descriptor, then the call fails, and newfd is not closed.
        *If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing, and returns newfd.

1)这两个函数我们可以用来复制文件描述符。
   2)其中oldfd和newfd分别是复制前文件描述符和复制后的文件描述符。
   3)这两个函数的调用都将复制文件描述符oldfd,且他们的返回值都为新的文件描述符。
    4)不同点是:dup()的返回值是最小的未用文件描述符;dup2()的返回值是预先制定的文件描述符newfd。
    5)对于dup2(),如果文件描述符newfd正在被使用,则先关闭newfd;如果newfd同oldfd,则不关闭该文件正常返回。
    PS:这是我自己对书上的话进行的分类。

2.首先要弄懂的话,还要对文件描述符了解的清晰:
       关系:进程---(拥有)--->(若干个)文件描述符()---(对应)--->文件
                            |--->文件秒素符(0)
                            |--->文件描述符(1)--->文件(1)
         某进程(n)--|--->文件描述符(2)
                            |--->文件描述符(3)--->文件(3)
                            |.
                            |.
                            |.
                            |--->文件描述符(1023)--->文件(...)
      PS1:由一次open()函数打开的文件是可以有很多个描述符与之相连的;
      PS2:Linux中每个进程可以有1024个文件描述符;
      PS3:文件描述符前三位0、1、2分别对应:
            STDIN_FILENO         0     标准输入文件
            STDOUT_FILENO     1     标准输出文件
            STDERR_FILENO     2     标准错误输出文件
  因此就可以较好的开始理解dup(int oldfd)和dup2(int oldfd, int newfd)函数是如何工作的:
      dup()比较好了解:
        系统分配一个新的、未用过的、值为最小的文件描述符指向dup()函数内的参数oldfd所指向的文件,并返回该值。
      dup2()比较难理解:
        1)dup2()先看看oldfd是不是一个有效的文件描述符,如果不是则调用失败,newfd文件描述符也不关闭;
        2)如果oldfd是一个有效的文件描述符,则检测newfd是否被使用,如在使用,则将其关闭,并将newfd指向oldfd所指向的文件,并返回newfd;
        3)如果newfd同oldfd,则不关闭该文件正常返回。

dup和dup2函数的更多相关文章

  1. dup和dup2函数以及管道的实现

    疑问:管道应该不是这样实现的,因为这要求修改程序的代码 dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符.它们经常用来重定向进程的stdin.stdout和stderr. ...

  2. 文件I/O(不带缓冲)之dup和dup2函数

    下面两个函数都可用来复制一个现有的文件描述符: #include <unistd.h> int dup( int filedes ); int dup2( int filedes, int ...

  3. Unix 网络编程 dup和dup2函数

    dup和dup2也是两个很实用的调用,它们的作用都是用来复制一个文件的描写叙述符. 它们经经常使用来重定向进程的stdin.stdout和stderr.这两个函数的原形例如以下: #include & ...

  4. linux之dup和dup2函数解析

    1. 文件描述符在内核中数据结构在具体说dup/dup2之前,我认为有必要先了解一下文件描述符在内核中的形态.一个进程在此存在期间,会有一些文件被打开,从而会返回一些文件描述符,从shell中运行一个 ...

  5. dup和dup2函数简单使用

    dup函数 头文件和函数原型: #include <unistd.h> int dup(int oldfd); dup函数是用来打开一个新的文件描述符,指向和oldfd同一个文件,共享文件 ...

  6. dup与dup2函数

    依赖的头文件 #include <unistd.h> 函数定义 int dup(int oldfd); int dup2(int oldfd, int newfd); 函数作用 dup和d ...

  7. dup和dup2用法小结

    今天和同学探讨了一下关于重定向输出到文件的问题,其中需要用到dup和dup2函数,因此来小小的总结一下. 首先来man一下: dup直接返回一个新的描述符和原来的描述符一样代表同一个资源,描述符的值就 ...

  8. dup和dup2详解

    C语言中dup和dup2函数的不同和使用 发表时间: 2012年11月15日 | 作者: 陈杰斌 | 所属分类: C语言 | 评论: 0 | 浏览: 1024 在unix高级编程中有介绍dup和dup ...

  9. dup and dup2的剖析

    转:http://www.cnblogs.com/sdphome/archive/2011/04/30/2033381.html dup和dup2都可用来复制一个现存的文件描写叙述符,使两个文件描写叙 ...

随机推荐

  1. <转>准备Eclips+python+robot framework环境

    关于python: path添加:C:\Python27;C:\Python27\Scripts; 新加一项:  PYTHON_HOME    C:\Python27 再不行的话,加一个用户变量: P ...

  2. QC开发只能修改指派给自己的缺陷,而其他的bug可以查看但是不允许修改

    今天在QC9.0项目中增加了几个项目,然后我的想法是:开发只能修改指派给自己的缺陷,而其他的bug可以查看但是不允许修改 虽说qc我还是比较熟悉的,但是对于这个问题,感觉可能要用到脚本,对于脚本我一窍 ...

  3. flex 图片旋转(解决公转和自转问题)

    在Flex中图片的旋转是既有公转和自转的.这样在图片旋转的时候就有一定小麻烦: 为了更好地说明问题,先引入两个概念:“自转”和“公转”.想象一下,地球在绕着太阳公转的同时,它自己也在自转.Flash应 ...

  4. 某酒店2000W数据

    某酒店2000W数据 2000万开房信息 [某酒店2000w数据 ct2000(解压密码:sjisauisa是就数据8很舒适好sjjss).rar] 国内安全漏洞监测平台乌云(WooYun.org)近 ...

  5. 《Genesis-3D开源游戏引擎完整实例教程-2D射击游戏篇01:播放序列动画》

    1.播放序列动画 系列动画播放概述 2D游戏中的动画系统,不同于3D游戏.3D游戏中,角色美术资源不仅包含角色模型的,还包括角色的贴图和动作等,模型本身自带角色的动作动画效果.2D游戏中,角色美术资源 ...

  6. 怎么利用SQL语句查询数据库中具体某个字段的重复行

    select * from [tablename] group by SeriNohaving count(SeriNo)<>1

  7. 新手指导:教你如何查看识别hadoop是32位还是64位

    问题导读: 1.从哪些地方可以识别hadoop是32位还是64位?2.hadoop本地库在什么位置? 来源:about云 本文链接:http://www.aboutyun.com/thread-127 ...

  8. iOS开发中使用Bmob RESTful API

    简介 尽管Bmob已经提供了一套SDK供开发者使用,但有时候开发者可能希望能直接与Bmob后台进行直接交互,以达到某些特别的需求(直接操作_User表.同步网络请求等).而RESTful API可以使 ...

  9. Another mysql daemon already running with the same unix socket

    在国外网站发现的解决方法. 原因多个Mysql进程使用了同一个socket. 两个方法解决: 第一个是立即关机 使用命令 shutdown -h now 关机,关机后在启动,进程就停止了. 第二个直接 ...

  10. 第二百八十七天 how can I 坚持

    终于把假请下来了,没有想象的那么复杂. 忘退车票了.明天应该有手续费了,现在又维护了,哎.10%的手续费了.7块钱,没了.希望不会白回去一趟啊. sql,group by  having .还是学不会 ...