dup2的函数定义为:

#include <unistd.h>

int dup2(int src_fd, int new_fd);

自己实现dup2函数有几个关键点:

1,检查给定的源fd是否有效,且都大于0,

2,检查目标fd是否超出了系统设定的范围,而这个值在书上是没有着重指出的,

  比如mac限制了要小于256,ubuntu限制是1024。

3,源fd与目标fd是否相等,

4,利用系统的特性:dup总是返回最小可用的fd,不断重复dup,从而得到一个等于new_fd的fd值

  再清除掉new_fd之前的临时fd

5,如果在4)的过程中。如果中途dup失败。则需要在返回失败前,关掉这些临时的fd。

  因此close这些临时fd时,需要区别是创建new_fd成功还是失败了。

下面是代码,仅限于类Unix系统环境:

 /*
* name : dup2.c
* func : implement of dup2 without fcntl.h
* author : jungle85gopy
* date : 2015.12.20
*/ /*
* Note :
* man dup() of Mac OSX
* Dup() duplicates an existing object descriptor and returns
* its value to the calling process (fildes2 = dup(fildes)).
* The value must be less than the size of the table, which is returned by
* getdtablesize(2). the size is 256 for Mac OSX 10.11.
* man dup() in ubuntu, there is no info about getdtablesize(2).
* but Ubuntu 14.04 still has getdtablesize limit of 1024.
*/ #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h> #define INIT_FD -2 int my_dup2(int src_fd, int new_fd);
int chk_dup(int src_fd, int new_fd);
int do_dup2(int src_fd, int new_fd); /*
* usage: dup2 src_fd, new_fd
*/
int main(int argc, char *argv[])
{
if (argc != ) {
printf("usage: dup2 src_fd new_fd\n");
exit();
} int new_fd = new_fd = my_dup2(atoi(argv[]), atoi(argv[]) );
if (new_fd == -) {
printf("dup to new_fd error!\n");
exit();
}
printf("\n[main]: new fd is %d\n", new_fd);
return new_fd;
} /*
* func: check the parameter of my_dup2
* return:
* -1: if error
* 0 : if success
*/
int chk_dup(int src_fd, int new_fd)
{
int tbl_size = getdtablesize(); printf("[my_dup2]: parameter : src fd %d\n", src_fd);
printf("[my_dup2]: parameter : new fd %d\n\n", new_fd); if (src_fd < || new_fd < ) {
printf("[my_dup2]: error: src or des parameter < 0.\n");
return -;
}
else if (new_fd >= tbl_size ) {
printf("[my_dup2]: error: des_fd out of system limit: %d\n", tbl_size);
return -;
} int index;
if ( (index = dup(src_fd)) == -) {
printf("[my_dup2]: parameter src_fd is inactive!\n");
return -;
} else
close(index); return ;
} /*
* func: dup a file descriptor from src_fd to new_fd
* return:
* new_fd if success
* -1 if error
*/
int my_dup2(int src_fd, int new_fd)
{
int ret; if ( (ret = chk_dup(src_fd, new_fd)) == -)
return -;
if (src_fd == new_fd)
return src_fd; // close new_fd, whether it is valid or not. ignore the return
close(new_fd); if ( (ret = do_dup2(src_fd, new_fd)) == -) {
printf("[my_dup2]: do dup failed!\n");
return -;
} else
return ret;
} /*
* func: dup from 0 to new_fd
*/
int do_dup2(int src_fd, int new_fd)
{
int index, index_hit = -, fd_array[new_fd]; for (index = ; index <= new_fd; index++)
fd_array[index] = INIT_FD; // initial to INIT_FD printf("[my_dup2]: before dup temp fds\n");
for (index = ; index <= new_fd; index++) {
fd_array[index] = dup(src_fd);
printf("[my_dup2]: index: %d, create temp fd: %d\n", index, fd_array[index]); if (fd_array[index] == -) {
printf("[my_dup2]: dup process error!\n");
break;
} else if (fd_array[index] == new_fd) {
index_hit = index;
break;
}
} // close temp fd
printf("\n[my_dup2]: to close temp fds\n"); if (index_hit == -) { // break for loops with error
for (index = ; index < new_fd; index++) {
if ((fd_array[index] == INIT_FD) || (fd_array[index] == -))
break; // no new temp dup in array
else {
close(fd_array[index]);
printf("[my_dup2]: index: %d, del temp fd: %d\n", index, fd_array[index]);
}
}
return -;
} else { // break for loops with hit
for (index = ; index < index_hit; index++) {
close(fd_array[index]);
printf("[my_dup2]: index: %d, temp fd: %d\n", index, fd_array[index]);
}
}
return new_fd;
}

[APUE]不用fcntl实现dup2函数功能的更多相关文章

  1. UNIX环境高级编程APUE练习3.2-不用fcntl实现dup2的功能

    1 题面 编写与dup2功能相同的函数,要求不调用fcntl函数,并且要有正确的出错处理. 2 基本思路 不能用fcntl,能够返回一个文件描述符的只有open和dup.而open会创建一个新的文件表 ...

  2. 第3章 文件I/O(4)_dup、dup2、fcntl和ioctl函数

    5. 其它I/O系统调用 (1)dup和dup2函数 头文件 #include<unistd.h> 函数 int dup(int oldfd); int dup2(int oldfd, i ...

  3. APUE中fcntl.h的使用及O_SYNC在Mac与Ubuntu下的测试

    此部分测试涉及到APUE V3中,第三章的图3-12到图3-14. 通过fcntl.h提供的功能,修改fd的文件属性,本处增加O_SYNC功能,并测试其效果. 本文涉及代码: tree ch3 ch3 ...

  4. linux之dup和dup2函数解析

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

  5. dup和dup2函数

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

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

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

  7. dup,dup2函数【转】

    转自:http://eriol.iteye.com/blog/1180624 转自:http://www.cnblogs.com/jht/archive/2006/04/04/366086.html ...

  8. 2-3 Sass的函数功能-列表函数

    列表函数主要包括一些对列表参数的函数使用,主要包括以下几种: length($list):返回一个列表的长度值: nth($list, $n):返回一个列表中指定的某个标签值 join($list1, ...

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

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

随机推荐

  1. 【SSM框架】Spring + Springmvc + Mybatis 基本框架搭建集成教程

    本文将讲解SSM框架的基本搭建集成,并有一个简单demo案例 说明:1.本文暂未使用maven集成,jar包需要手动导入. 2.本文为基础教程,大神切勿见笑. 3.如果对您学习有帮助,欢迎各种转载,注 ...

  2. category中重写方法?

    问:可以在category中重写方法吗? 答:代码上可以实现 在category中重写方法,但在实际开发中,不建议这样做.如果确实需要重写原有方法也建议使用子类进行重写. category是为了更方便 ...

  3. Java消息队列--ActiveMq 实战

    1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...

  4. DOM的小练习,两个表格之间数据的移动

    本次讲的是两个表格之间数据的移动,左边的表格移动到右边,并且左边表格移动内容消失. <head>   <meta http-equiv="Content-Type" ...

  5. 【微信小程序开发•系列文章六】生命周期和路由

    这篇文章理论的知识比较多一些,都是个人观点,描述有失妥当的地方希望读者指出. [微信小程序开发•系列文章一]入门 [微信小程序开发•系列文章二]视图层 [微信小程序开发•系列文章三]数据层 [微信小程 ...

  6. JAVA环境变量和TomCat服务器配置

    Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选.对于一个初学者来说,可以这样 ...

  7. 如何理解MySQL中auto_increment?

    1.auto_increment用于主键自动增长.比如从1开始增长,当把第一条数据删除,再插入第二条数据时,主键值为2,不是1.

  8. 记录在Windows上安装和使用Oracle数据库过程中的坑

    1.安装Oracle Oracle软件是免费的,可以去官网下载相应的安装包.但是如果用于商业用途需要购买License.官网上针对各种平台,32位和64位都有,如果在Windows一般会下载到两个文件 ...

  9. Win10连接远程桌面时提示“您的凭据不工作”

    我遇到这个问题的时候查找网上都给出一堆高大上的解决办法, 然而我的错误实际上是用户名的问题, 很多人以为远程用户名就一定是锁屏状态下的登录名, 其实不是,跟自己设置有关,所以首先应该检查远程用户名是否 ...

  10. OpenSUSE下编译安装OpenFoam

    在不是Ubuntu系统下安装OpenFoam,需要采用编译安装的方式.以下以OpenSuSE为例进行编译安装. 1 软件包准备 需要下载两个程序包: OpenFOAM-4.x-version-4.1. ...