[APUE]不用fcntl实现dup2函数功能
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函数功能的更多相关文章
- UNIX环境高级编程APUE练习3.2-不用fcntl实现dup2的功能
1 题面 编写与dup2功能相同的函数,要求不调用fcntl函数,并且要有正确的出错处理. 2 基本思路 不能用fcntl,能够返回一个文件描述符的只有open和dup.而open会创建一个新的文件表 ...
- 第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 ...
- APUE中fcntl.h的使用及O_SYNC在Mac与Ubuntu下的测试
此部分测试涉及到APUE V3中,第三章的图3-12到图3-14. 通过fcntl.h提供的功能,修改fd的文件属性,本处增加O_SYNC功能,并测试其效果. 本文涉及代码: tree ch3 ch3 ...
- linux之dup和dup2函数解析
1. 文件描述符在内核中数据结构在具体说dup/dup2之前,我认为有必要先了解一下文件描述符在内核中的形态.一个进程在此存在期间,会有一些文件被打开,从而会返回一些文件描述符,从shell中运行一个 ...
- dup和dup2函数
下面两个函数都可用来复制一个现存的文件描述符: #include<unistd.h> int dup(int filedes); int dup2(int filedes,int file ...
- dup和dup2函数以及管道的实现
疑问:管道应该不是这样实现的,因为这要求修改程序的代码 dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符.它们经常用来重定向进程的stdin.stdout和stderr. ...
- dup,dup2函数【转】
转自:http://eriol.iteye.com/blog/1180624 转自:http://www.cnblogs.com/jht/archive/2006/04/04/366086.html ...
- 2-3 Sass的函数功能-列表函数
列表函数主要包括一些对列表参数的函数使用,主要包括以下几种: length($list):返回一个列表的长度值: nth($list, $n):返回一个列表中指定的某个标签值 join($list1, ...
- Unix 网络编程 dup和dup2函数
dup和dup2也是两个很实用的调用,它们的作用都是用来复制一个文件的描写叙述符. 它们经经常使用来重定向进程的stdin.stdout和stderr.这两个函数的原形例如以下: #include & ...
随机推荐
- Git 子模块 - submodule
有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目. 也许是第三方库,或者你 独立开发的,用于多个父项目的库. 现在问题来了:你想要把它们当做两个独立的项目,同时又想在 一个项目中使用另 ...
- 【小程序分享篇 二 】web在线踢人小程序,维持用户只能在一个台电脑持登录状态
最近离职了, 突然记起来还一个小功能没做, 想想也挺简单,留下代码和思路给同事做个参考. 换工作心里挺忐忑, 对未来也充满了憧憬与担忧.(虽然已是老人, 换了N次工作了,但每次心里都和忐忑). 写写代 ...
- Fabio 安装和简单使用
Fabio(Go 语言):https://github.com/eBay/fabio Fabio 是一个快速.现代.zero-conf 负载均衡 HTTP(S) 路由器,用于部署 Consul 管理的 ...
- vue2.0实践的一些细节
最近用vue2.0做了个活动.做完了回头发现,好像并没有太多的技术难点,而自己好像又做了比较久...只能说效率有待提升啊...简单总结了一些比较细节的点. 1.对于一些已知肯定会有数据的模块,先用一个 ...
- Key/Value之王Memcached初探:二、Memcached在.Net中的基本操作
一.Memcached ClientLib For .Net 首先,不得不说,许多语言都实现了连接Memcached的客户端,其中以Perl.PHP为主. 仅仅memcached网站上列出的语言就有: ...
- UWP开发之Mvvmlight实践九:基于MVVM的项目架构分享
在前几章介绍了不少MVVM以及Mvvmlight实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎 ...
- jquery屏幕滚动计算事件总结
获取浏览器显示区域(可视区域)的高度 : $(window).height(); 获取浏览器显示区域(可视区域)的宽度 : $(window).width(); 获取页面的文档高度: $(docume ...
- MediatorPattern(中介者模式)
/** * 中介者模式 * @author TMAC-J * 研究了这么多设计模式,觉得无非就是几点: * 1.若两个类有耦合关系,设立一个中间类,处理两个类的关系,把两个类的耦合降低 * 2.面向接 ...
- SAP CRM 树视图(TREE VIEW)
树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...
- 【干货分享】流程DEMO-补打卡
流程名: 补打卡申请 业务描述: 当员工在该出勤的工作日出勤但漏打卡时,于一周内填写补打卡申请. 流程相关文件: 流程包.xml 流程说明: 直接导入流程包文件,即可使用本流程 表单: 流程: 图片 ...