dup 和 dup2
    dup和dup2,都是用来将一个文件描述符复制给另一个文件描述符上,这两个文件描述符都指向同一个文件状态标志上。
  只是文件描述符的大小不一样,dup所执行下的复制,肯定是返回的系统中最小的可用文件描述符。而dup2.可以自定义文件描述符的。系统的0、1、2描
  述符已经被占用。所以用dup所复制的描述符是不能是这三个的。我们可以将这三个复制给其他的文件描述符。

函数描述

  int dup(int filedes)

  int dup2(int filedes, int filedes2)

dup

   dup的参数是filedes,这个指的是系统中已经打开的文件描述符.返回的确实一个可用的最小文件描述符。

  利用fcntl,我们可以将其分解看:fcntl(filedes ,F_DUPFD,0)

   可以很简单的看一下这三个参数,第一是我们要复制的文件描述符,第二个是fcntl的状态标志,指的是dup一个文件描述符。第三个参数,我们很容易理解错,这边写的是0,有可能你会认为是将0号描述符给返回出去,其实不是,他的是意思 是,返   回一个比这个数大或是等于他的最小描述符。这个和dup的功能解释是符合的。

dup2

  他的参数是有俩,filedes和前面的一样,是我们要复制的文件描述符,后面的filedes2,则是我们想要函数返回的文件描述符,很好理解。

   同样这fcntl中我们可以很清晰的看出:fcntl(filedes, F_DUPFD,filedes2).

  先前的“0”,被我们用filedes2直接替代了。函数返回的就是我们设置的那个filedes2。

confuse

  dup2,对于这个函数,我们可以自己定义文件描述符,这就有一个容易混淆的地方,如果我们将fd定义为从STDIN_FILENO复制过来的,现在我们用fd2 = dup2(fd,1)。我们知道文件描述符1已经是被标准输出占用了,你会说我们现在是在将标准输入   复制给“标准输出”,先不想这个!按照原先的思路现在我们用的fd2应该就是一个标准输入,我们可以拿他来从屏幕上读一个串数据,然后显示到终端上,这个是可以做到的。但是你会说这个fd2不是被赋予了1的描述符吗?怎么可以用作标准输入    呢?回到dup2的定义,dup2在执行的过程中,会看这个filedes2是不是已经打开? 如果打开了,就将其关闭。然后再执行复制,也就是说,这边的fd2就是指向的标准输入了。一个描述符只能指向一个文件状态标志的。所以这个是不冲突的。而标  准输入已经被关闭了。下面是这个confuse验证代码:

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h> #define BUFSIZE 4096 int main(void)
{
int fd;
int fd2,n;
char buf[BUFSIZE]; fd = dup(STDIN_FILENO);
if(fd < )
{
fprintf(stderr,"dup:%s\n",strerror(errno));
exit();
}
fd2 = dup2(fd,);
if(fd2<)
{
fprintf(stderr,"dup2:%s\n",strerror(errno));
exit();
} printf("fd = %d \n",fd);
printf("fd2 = %d \n",fd2); if((n =read(fd,buf,BUFSIZE)) < )
{
fprintf(stderr,"read:%s\n",strerror(errno));
exit();
} if(write(fd2,buf,n) != n)
{
fprintf(stderr,"write:%s\n",strerror(errno));
exit();
} close(fd);
close(fd2);
return ;
}

结果截图:

My_dup2

  要求: 要实现自己写一个dup2,不使用fcntl函数,有正确的错误提示。

  分析: 不使用fcntl函数,那就只有使用dup来实现这个dup2了。我们的目的就是让自己所定义的描述符能过符合要求,系统有个要求,最大的描述符不能超过63,也就是最多打开64个描述符,这是第一个要检查的。继而我们检查,这个所定义的描    述符,和我要复制的这个描述符是不是相等的,要是相等的话,那就直接返回了。这是第二个要检查的。好了,这些都符合要求,那么我们就定义一个额外的文件描述符(区别于你给定的文件描述符)。我们用这个额外的一个描述符来接受我们对    我们要复制的描述符的dup的返回值。将这个返回值和你所给定的比对,如果相等就将这个fd返回,说明已经将其复制好。也就完成了dup2的工作了。 解释一下为什么要这么做: dup的返回值是系统中最小的可用的文件描述符,所以我们不能    够一下子就能确定dup返回的这个文件描述符就是你所指定的,同时dup操作也是在将你说指定文件描述符指向你所要复制的那个文件描述符指向的文件状态标志上去(实际上不是,实际上同过dup不断打开的文件描述符,将在你所指定的文件描    述符前的文件描述符占用掉,被迫你的返回你所指定的文件描述符。所以我们要将这些之前不是我们所需的文件描述符保存到一个数组中,待最后找到指定的描述符后就将一一释放掉。)

下面的一个给出可行的代码:

 /************************************************************************************************************
*程序目的是通过dup实现dup2,并用通过dup2所返回的文件描述符实现文件的写操作
*************************************************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h> //系统在fcntl这个头文件里应该有OPEN_MAX这个参数的,不过我的系统上引入头文件也是没用的
//故用条件编译的原理让其自动判断并定义
#ifndef OPEN_MAX
#define OPEN_MAX 256
#endif char buf1[] = "abcdefg";
char buf2[] = "ABCDEFG"; int mydup2(int ,int); int main()
{
int fd,fd2; fd = open("a.txt",O_RDWR|O_CREAT,);
if(fd < )
{
fprintf(stderr, "open:%s\n",strerror(errno));
exit();
} if(write(fd,buf1,strlen(buf1)) != strlen(buf1))
{
fprintf(stderr,"write:%s\n",strerror(errno));
exit();
}
//实现文件描述符的复制
fd2 = mydup2(fd,); if(write(fd2,buf2,strlen(buf2)) != strlen(buf2))
{
fprintf(stderr,"write2:%s\n",strerror(errno));
exit();
} printf("fd2:%d\n",fd2); return ; } int mydup2(int filedes,int filedes2)
{
int fd[OPEN_MAX];
int i =-;
int tfd;
//检查你指定的文件描述符是否合法
if(filedes < || filedes2 < || filedes2 > OPEN_MAX)
{
printf("filedes is error!\n");
exit();
} if(filedes == filedes2)
{
return filedes2;
}
close(filedes2);
//这边是遍历寻找你所指定的文件描述符
tfd = dup(filedes);
while(filedes2 != tfd)
{
i++;
fd[i] = tfd;
tfd = dup(filedes);
}
//释放之前打开的没有用的文件描述符
while(i>=)
{
close(fd[i]);
i--;
}
return filedes2;
}

运行结果:

上述也就是对dup和dup2的一些理解。谷歌了半天发现这类的资料写的都比较官方,自己看不大懂,自己写下自己的一些理解,也是算是自己的一个学习的验证了。

Unix环境高级编程学习笔记——dup的更多相关文章

  1. Unix环境高级编程学习笔记——fcntl

    写这篇文正主要是为了介绍下fcntl,并将我自己在学习过程中的一些理解写下来,不一定那么官方,也有错误,希望指正,共同进步- fcntl: 一个修改一打开文件的性质的函数.基本的格式是 int fcn ...

  2. UNIX环境高级编程学习笔记(十)为何 fork 函数会有两个不同的返回值【转】

    转自:http://blog.csdn.net/fool_duck/article/details/46917377 以下是基于 linux 0.11 内核的说明. 在init/main.c第138行 ...

  3. [置顶] 文件和目录(二)--unix环境高级编程读书笔记

    在linux中,文件的相关信息都记录在stat这个结构体中,文件长度是记录在stat的st_size成员中.对于普通文件,其长度可以为0,目录的长度一般为1024的倍数,这与linux文件系统中blo ...

  4. unix环境高级编程-读书笔记与习题解答-第一篇

    从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...

  5. 《UNIX环境高级编程》笔记--UNIX标准化及实现

    1.UNIX标准化 1.1.ISO C 1989 年后期,C程序设计语言的ANSI(American National Standards Institute) 标准X3. 15 9-1989得到批准 ...

  6. 《UNIX环境高级编程》笔记——3.文件IO

    一.引言 说明几个I/O函数:open.read.write.lseek和close,这些函数都是不带缓冲(不带缓冲,只调用内核的一个系统调用),这些函数不输入ISO C,是POSIX的一部分: 多进 ...

  7. 《UNIX环境高级编程》笔记——2.标准和实现

    随着UNIX各种衍生版本不断发展壮大,标准化工作就十分必要.其实干啥事都是这样,玩的人多了,必须进行标准化. 一.UNIX标准 1.1 ISO C(ANSI C) ANSI:Amerocan Nato ...

  8. 《UNIX环境高级编程》笔记——1.UNIX基础知识

    这一章节侧重一些基本概念和书中用到的一些名词. 一.引言 所有的操作都提供服务,典型的服务包括:执行新程序.打开文件.读写文件.分配存储区以及获得当前时间等. 二.UNIX体系结构 其实linux常见 ...

  9. unix 环境高级编程 读书笔记与习题解答第四篇

    第一章 第六节 第一小节 这一章没有程序设计和API方面的深入学习,而是注重介绍了unix操作系统中的原始数据类型和系统原型函数,错误处理方面的知识. ____unistd.h____ 该文件包含了u ...

随机推荐

  1. PC-破解RAR软件注册问题

    打开RAR文件提示软件注册 压缩软件WinRAR并不是免费软件,用了40天后,每次解压文件时都会弹出一提示,问你是否购买(但不影响功能),下面说下最新版的WinRAR v3.71(现在有更新版了,一样 ...

  2. HDU 4635 - Strongly connected(2013MUTC4-1004)(强连通分量)

    t这道题在我们队属于我的范畴,最终因为最后一个环节想错了,也没搞出来 题解是这么说的: 最终添加完边的图,肯定可以分成两个部X和Y,其中只有X到Y的边没有Y到X的边,那么要使得边数尽可能的多,则X部肯 ...

  3. bootstrap-table对前台页面表格的支持

    1.bootstrap-table是在bootstrap的基础上面做了一些封装,所以在使用bootstrap-table之前要导入的js和css有 1)基本的还是jQuery <script t ...

  4. cocos2d-x触屏事件(单点触屏)

    转自:http://blog.csdn.net/onerain88/article/details/7550009 一般经常用到的触屏的情况有两种:一种是Layer统一接收触屏消息,然后由程序根据需要 ...

  5. 开发XMPP IM

    Openfire 是一个用Java 实现的XMPP 服务器,客户端可以通过IQ的方式与其进行通信(其实就是XML),客户端和服务器之间的通信是依靠底层Smack 库提供的各种功能来完成的.其实利用插件 ...

  6. [置顶] android LBS的研究与分享(附PPT)

    早上起床后想想以前的工作有什么可以分享的... 两年前,前公司在做一个陌生人交友的社交软件(比陌陌还早),需要研究LBS的相关工作(这里面主要研究的是Google定位)... 一.简要调研结果 很多 ...

  7. [ES6] 23. Rest Parameters & Spread Parameters

    Rest Parameters: In ES5, when you don't know how many paramters will be passed in, you can use argum ...

  8. linux上安装memcached

    我的版本为Centos Release 5.3 (Final)使用这个命令可以知道你的Linux版本1.cat /etc/redhat-release首先要安装libevent库.cd /usr/lo ...

  9. android开发之shape详解

    很多时候,使用shape能够实现的效果,你用一张图片也能够实现,但问题是一张图片无论你怎么压缩,它都不可能比一个xml文件小,因此,为了获得一个高性能的手机App,我们在开发中应该遵循这样一个原则:能 ...

  10. Ⅶ.spring的点点滴滴--自定义对象行为

    承接上文 自定义对象行为 .net篇(环境为vs2012+Spring.Core.dll v1.31) public class lifeCycle : Spring.Objects.Factory. ...