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. LINUX篇,设置MYSQL远程访问实用版

    每次设置root和远程访问都容易出现问题, 总结了个通用方法, 关键在于实用 step1: # mysql -u root mysql mysql> Grant all privileges o ...

  2. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  3. Android 判断一个 View 是否可见 getLocalVisibleRect(rect) 与 getGlobalVisibleRect(rect)

    Android 判断一个 View 是否可见 getLocalVisibleRect(rect) 与 getGlobalVisibleRect(rect) [TOC] 这两个方法的区别 View.ge ...

  4. iOS热更新-8种实现方式

    一.JSPatch 热更新时,从服务器拉去js脚本.理论上可以修改和新建所有的模块,但是不建议这样做. 建议 用来做紧急的小需求和 修复严重的线上bug. 二.lua脚本 比如: wax.热更新时,从 ...

  5. SQL Server 常用内置函数(built-in)持续整理

    本文用于收集在运维中经常使用的系统内置函数,持续整理中 一,常用Metadata函数 1,查看数据库的ID和Name db_id(‘DB Name’),db_name('DB ID') 2,查看对象的 ...

  6. 客户端的验证插件validator

    简单,智能,令人愉悦的表单验证~~~ 官方文档:http://www.niceue.com/validator/ <!DOCTYPE html> <html> <head ...

  7. 前端MVC学习总结(一)——MVC概要与angular概要、模板与数据绑定

    一.前端MVC概要 1.1.库与框架的区别 框架是一个软件的半成品,在全局范围内给了大的约束.库是工具,在单点上给我们提供功能.框架是依赖库的.AngularJS是框架而jQuery则是库. 1.2. ...

  8. 【基于WinForm+Access局域网共享数据库的项目总结】之篇一:WinForm开发总体概述与技术实现

    篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...

  9. [转载]强制不使用“兼容性视图”的HTML代码

    在IE8浏览器以后版本,都有一个"兼容性视图",让不少新技术无法使用.那么如何禁止浏览器自动选择"兼容性视图",强制IE以最高级别的可用模式显示内容呢?下面就介 ...

  10. Maven 整合FreeMarker使用

    pom.xml <!-- freemarker jar --> <dependency> <groupId>org.freemarker</groupId&g ...