• [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系统环境:

      1 /*
      2  * name     : dup2.c
      3  * func     : implement of dup2 without fcntl.h
      4  * author   : jungle85gopy
      5  * date     : 2015.12.20
      6  */
      7 
      8 /*
      9  * Note :
     10  *  man dup() of Mac OSX
     11  *      Dup() duplicates an existing object descriptor and returns
     12  *          its value to the calling process (fildes2 = dup(fildes)).
     13  *       The value must be less than the size of the table, which is returned by
     14  *          getdtablesize(2). the size is 256 for Mac OSX 10.11.
     15  *  man dup() in ubuntu, there is no info about getdtablesize(2).
     16  *      but Ubuntu 14.04 still has getdtablesize limit of 1024.
     17  */
     18 
     19 #include <unistd.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <sys/utsname.h>
     23 
     24 
     25 #define  INIT_FD   -2
     26 
     27 int my_dup2(int src_fd, int new_fd);
     28 int chk_dup(int src_fd, int new_fd);
     29 int do_dup2(int src_fd, int new_fd);
     30 
     31 /*
     32  * usage: dup2 src_fd, new_fd
     33  */
     34 int main(int argc, char *argv[])
     35 {
     36     if (argc != 3) {
     37         printf("usage: dup2 src_fd new_fd
    ");
     38         exit(1);
     39     }
     40 
     41     int new_fd = new_fd = my_dup2(atoi(argv[1]), atoi(argv[2]) );
     42     if (new_fd == -1) {
     43         printf("dup to new_fd error!
    ");
     44         exit(1);
     45     }
     46     printf("
    [main]: new fd is %d
    ", new_fd);
     47     return new_fd;
     48 }
     49 
     50 /*
     51  * func: check the parameter of my_dup2
     52  * return:
     53  *      -1: if error
     54  *      0 : if success
     55  */
     56 int chk_dup(int src_fd, int new_fd)
     57 {
     58     int tbl_size = getdtablesize();
     59 
     60     printf("[my_dup2]: parameter : src fd %d
    ", src_fd);
     61     printf("[my_dup2]: parameter : new fd %d
    
    ", new_fd);
     62 
     63     if (src_fd < 0 || new_fd < 0 ) {
     64         printf("[my_dup2]: error: src or des parameter < 0.
    ");
     65         return -1;
     66     }
     67     else if (new_fd >= tbl_size ) {
     68         printf("[my_dup2]: error: des_fd out of system limit: %d
    ", tbl_size);
     69         return -1;
     70     }
     71 
     72     int index;
     73     if ( (index = dup(src_fd)) == -1) {
     74         printf("[my_dup2]: parameter src_fd is inactive!
    ");
     75         return -1;
     76     } else
     77         close(index);
     78 
     79     return 0;
     80 }
     81 
     82 
     83 /*
     84  * func: dup a file descriptor from src_fd to new_fd
     85  * return:
     86  *      new_fd if success
     87  *      -1     if error
     88  */
     89 int my_dup2(int src_fd, int new_fd)
     90 {
     91     int ret;
     92 
     93     if ( (ret = chk_dup(src_fd, new_fd)) == -1)
     94         return -1;
     95     if (src_fd == new_fd)
     96         return src_fd;
     97 
     98     // close new_fd, whether it is valid or not. ignore the return
     99     close(new_fd);
    100 
    101     if ( (ret = do_dup2(src_fd, new_fd)) == -1) {
    102         printf("[my_dup2]: do dup failed!
    ");
    103         return -1;
    104     } else
    105         return ret;
    106 }
    107 
    108 
    109 /*
    110  * func: dup from 0 to new_fd
    111  */
    112 int do_dup2(int src_fd, int new_fd)
    113 {
    114     int index, index_hit = -1, fd_array[new_fd];
    115 
    116     for (index = 0; index <= new_fd; index++)
    117         fd_array[index] = INIT_FD;   // initial to INIT_FD
    118 
    119     printf("[my_dup2]: before dup temp fds
    ");
    120     for (index = 0; index <= new_fd; index++) {
    121         fd_array[index] = dup(src_fd);
    122         printf("[my_dup2]: index: %d, create temp fd: %d
    ", index, fd_array[index]);
    123 
    124         if (fd_array[index] == -1) {
    125             printf("[my_dup2]: dup process error!
    ");
    126             break;
    127         } else if (fd_array[index] == new_fd) {
    128             index_hit = index;
    129             break;
    130         }
    131     }
    132 
    133     // close temp fd
    134     printf("
    [my_dup2]: to close temp fds
    ");
    135 
    136     if (index_hit == -1) {   // break for loops with error
    137         for (index = 0; index < new_fd; index++) {
    138             if ((fd_array[index] == INIT_FD) || (fd_array[index] == -1))
    139                 break;      // no new temp dup in array
    140             else {
    141                 close(fd_array[index]);
    142                 printf("[my_dup2]: index: %d, del temp fd: %d
    ", index, fd_array[index]);
    143             }
    144         }
    145         return -1;
    146     } else {                // break for loops with hit
    147         for (index = 0; index < index_hit; index++) {
    148             close(fd_array[index]);
    149             printf("[my_dup2]: index: %d, temp fd: %d
    ", index, fd_array[index]);
    150         }
    151     }
    152     return new_fd;
    153 }
  • 相关阅读:
    软件的竞争力:性能 CQ
    2010.7.11 OA项目组一周工作报告 CQ
    2010.8.22 OA项目组一周工作报告 CQ
    2010.7.18 OA 项目组一周工作报告 CQ
    我的音乐 CQ
    2010.7.25 OA项目组一周工作报告 CQ
    JavaScript中的关于this
    递归函数的应用
    es6中的对象的可计算的属性名
    undefined 和 undeclared 的区别
  • 原文地址:https://www.cnblogs.com/qinqiao/p/implement_dup2.html
Copyright © 2020-2023  润新知