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. Combobox 成员添加

    this.comboBox1.Items.AddRange(new object[] {"Item 1", "Item 2", "Item 3&quo ...

  2. 问题-delphi 调试(F8)错行处理

    在delphi 7中(其他版本也可能碰到该问题),编译后,代码左边显示蓝色小点,表示哪句代 码是被编译了的,可今天我的一些代码不能显示那些蓝点了,这样也就不能在上面设断点了,而且用F8跟踪发现执行的顺 ...

  3. CAS 之 集成RESTful API

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  4. c# 判断网络是连接到互联网

    方法1:InternetGetConnectedState         [System.Runtime.InteropServices.DllImport("wininet") ...

  5. List IEnumerable

    //按部门汇总            IEnumerable<WeekReportWithDepartmentInfo> report = summary            .Grou ...

  6. MyEclipse的快捷键的使用

    MyEclipse的10个快捷键:Ctrl + Shift + T: 打开类型:显示"打开类型"对话框来在编辑器中打开类型."打开类型"选择对话框显示工作空间中 ...

  7. android的activity的跳转

    1.无参数的跳转 先在layout下建立一个factivity.xml,在里面添加2个Button按钮和一个TextView,并添加属性 , 然后建立以个sactivity.xml文件, 在src下建 ...

  8. Android开发——构建自定义组件

    Android中,你的应用程序程序与View类组件有着一种固定的联系,例如按钮(Button). 文本框(TextView), 可编辑文本框(EditText), 列表框(ListView), 复选框 ...

  9. java Spring 基于注解的配置(一)

    注解引用:1.service.xml 配置注解模式 <?xml version="1.0" encoding="UTF-8"?> <beans ...

  10. 调试环境部署续:vs远程调试

    原文http://www.bitscn.com/weixin/464994.html 第一步  IIS的配置 进入iis,点击网址,选择你的网站,在窗口的右边编辑网站中点击绑定,如图所示. 进入网站绑 ...