[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 & ...
随机推荐
- 你必须知道的EF知识和经验
注意:以下内容如果没有特别申明,默认使用的EF6.0版本,code first模式. 推荐MiniProfiler插件 工欲善其事,必先利其器. 我们使用EF和在很大程度提高了开发速度,不过随之带来的 ...
- [高并发]Java高并发编程系列开山篇--线程实现
Java是最早开始有并发的语言之一,再过去传统多任务的模式下,人们发现很难解决一些更为复杂的问题,这个时候我们就有了并发. 引用 多线程比多任务更加有挑战.多线程是在同一个程序内部并行执行,因此会对相 ...
- HTML DOM 对象
本篇主要介绍HTML DOM 对象:Document.Element.Attr.Event等4个对象. 目录 1. Document 对象:表示文档树的根节点,大部分属性和方法都是对元素进行操作. 2 ...
- javascript单元测试框架mochajs详解
关于单元测试的想法 对于一些比较重要的项目,每次更新代码之后总是要自己测好久,担心一旦上线出了问题影响的服务太多,此时就希望能有一个比较规范的测试流程.在github上看到牛逼的javascript开 ...
- sql的那些事(一)
一.概述 书写sql是我们程序猿在开发中必不可少的技能,优秀的sql语句,执行起来吊炸天,性能杠杠的.差劲的sql,不仅使查询效率降低,维护起来也十分不便.一切都是为了性能,一切都是为了业务,你觉得你 ...
- 缓存、队列(Memcached、redis、RabbitMQ)
本章内容: Memcached 简介.安装.使用 Python 操作 Memcached 天生支持集群 redis 简介.安装.使用.实例 Python 操作 Redis String.Hash.Li ...
- peer not authenticated的终极解决方案
一.前述 使用httpclient发起https请求时,可能会遇到如下异常: javax.net.ssl.SSLPeerUnverifiedException: peer not authentica ...
- java中易错点(二)
java,exe是java虚拟机 javadoc.exe用来制作java文档 jdb.exe是java的调试器 javaprof,exe是剖析工具 解析一: sleep是线程类(Thread)的方法, ...
- Android—Volley:接收服务端发送的json数据乱码问题解决
new JsonObjectRequest中重写方法parseNetworkResponse,内容如下: /** * 重写此方法不会导致乱码 */ @Override protected Respon ...
- grep 查找bash脚本中的注释代码
出于安全性的考虑,不建议在bash脚本中注释掉不使用的代码.也就是说如果某段代码不使用了,那么应该删除掉,而不是简单地注释掉.假如你突然意识到这一点,而以前并没有遵从这个原则,现在需要找出脚本中的注释 ...