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. Java 常见异常及趣味解释

    java.lang ArithmeticException 你正在试图使用电脑解决一个自己解决不了的数学问题,请重新阅读你的算术表达式并再次尝试. ArrayIndexOutOfBoundsExcep ...

  2. 【转】科普Spark,Spark是什么,如何使用Spark

    本博文是转自如下链接,为了方便自己查阅学习和他人交流.感谢原博主的提供! http://www.aboutyun.com/thread-6849-1-1.html http://www.aboutyu ...

  3. sp_send_dbmail权限问题

    这段时间处理SSIS服务器迁移的事情,在处理一个发送邮件的任务的时候,突然出现如下错误,  拒绝了对对象 'sp_send_dbmail' (数据库 'msdb',架构 'dbo')的 EXECUTE ...

  4. 这难道是CSDN的BUG? 大家帮忙看看哪里有问题

    问题: 有位网友发私信给我,提问关于网络project专业以后这么就业,要掌握哪些技术? 我就给回复, 内容例如以下: 你好,很抱歉这么晚才给你回复.对于网络project专业,就业范围事实上挺广泛的 ...

  5. 【转】C++中了类继承和调用父类的构造函数方法

    构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法).因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统需 ...

  6. HDU4619+匈牙利

    /* 匈牙利算法 二分匹配 最小点覆盖=最大匹配. 即踢掉最小点覆盖 */ #include<stdio.h> #include<string.h> #include<s ...

  7. 用sp_addlinkedserver建立链接服务器(sql server2008中通过测试)

    --在SQL SERVER 2008里,可以按以下的方式建立链接服务器 ? EXEC  sp_addlinkedserver          @server='Test',--这里是给链接服务器取的 ...

  8. dubbox开发rest+json指南【转】

    http://dangdangdotcom.github.io/dubbox/rest.html 目录 概述 REST的优点 应用场景 快速入门 标准Java REST API:JAX-RS简介 RE ...

  9. java对空格的处理

    public static void main(String[] args) { // TODO Auto-generated method stub String a = " 这个前面有两 ...

  10. linux上安装shell编辑器与linux运维面试题

    分两个部分 一.安装B-shell解释器 安装cygwin  Eclipse要找到安装的bin路径 https://cygwin.com 二.安装编辑器shellEd 下载可以得到一个:net.sou ...