UNIX环境高级编程习题之第三章第二题

来源:互联网 发布:基价的算法和作用 编辑:程序博客网 时间:2024/05/18 00:51

不调用fcntl函数实现dup2函数


问题描述

dup2函数头定义为int dup2(int fd, int fd2),返回值为fd2指定的文件描述符,指向fd指向的文件,如果fd2已经打开,则需先关闭;如果fd == fd2,则无需关闭fd2。

解题思路

1、寻找需要的文件描述符
不能调用fcntl,那么我们只能调用dup函数,这个函数会返回当前可用的文件描述符中的最小值,循环n次调用直到返回值等于fd2。

2、调用dup的负面影响
这个时候我们打开了n-1个无用的文件,这些并不是我们需要或者预期的,返回前需关闭。否则不但会占用大量系统资源,使得系统无法打开新的文件,甚至这些预期之外的文件描述符也可以访问或者修改文件,形成安全隐患。

3、消除dup造成的隐患
线性结构记录n-1个文件描述符,并依次关闭

4、错误error处理
dup调用错误:包括指定的fd2过大,打开的文件描述符超出限制。在不考虑其他程序也调用此函数的情况下,我们可以通过sysconf函数来获取打开上限。

5、测试问题
定义一个文件描述符x指向标准输出,并通过x写入一段特定的字符,查看是否会在标准输出是打印,也可以直接重定向到指定文件查看。

代码实现

本文采用c语言实现该逻辑:

#include "apue.h"#include <myerr.h>#include <limits.h>#include <unistd.h>#include <errno.h>#ifdef OPEN_MAXstatic long openmax = OPEN_MAX;#elsestatic long openmax = 0;#endifint mydup(int fd, int fd2){    //获取系统允许的最大的文件数    errno = 0;    if (openmax == 0)        openmax = sysconf(_SC_OPEN_MAX);    if (openmax < 0){        if (errno != 0){ //这个值是不确定的            printf("OPEN_MAX这个值是不确定的,设为默认100\n");            openmax = 100;        }        else{ //获取OPEN_MAX错误            printf("获取OPEN_MAX错误,设为默认100\n");            openmax = 100;        }    }else        printf("OPEN_MAX获取成功,其值是%ld\n", openmax);    //关闭指定的fd2文件    errno = close(fd2);    //关闭文件不一定会成功,因为有可能这个文件本身就没有打开,所以错误也不退出    if (errno == -1)         printf("关闭fd2错误:%d",errno);    //获取待返回的文件描述符fd1    long fd1 = -1;    int arr[openmax-1], idx = 0,i;    for (i = 0; i < openmax - 1; i++){// 初始化线性结构        arr[i] = -1;    }    do{//循环调用dup函数直至返回的fd1 == fd2        fd1 = dup(fd);        if (fd1 > 0){//调用成功            if (fd1 == fd2){//如果调用成功,退出循环                break;            }else{                arr[idx] = fd1;                idx++;            }        }    }while(fd1 < fd2);    //关闭打开的多余的文件    for (i = 0; i < openmax - 1; i++){        if (arr[i] == -1)            break;        else{            errno = close(arr[i]);            if (errno == -1){                printf("关闭文件%ld错误",arr[i],stdout);                if (idx != i){                    idx = i;                    i--; //关闭失败回退再关闭一次                }            }        }    }    return fd1;}int main(void){    int fdtest = dup(1);    char buf[] = "hello, mydup for dup2!\n";    printf("打开的文件是:%d,buf长度是%d\n",fdtest,strlen(buf));    int fd = mydup(STDOUT_FIFLNO,fdtest);    printf("mydup返回的文件是:%d\n",fd);    //测试返回的文件符是否可以直接操作标准输出    if (write(fd, buf, strlen(buf)) != strlen(buf))        err_sys("buf write error\n");    exit(0);}

在Linux环境下的运行结果如下:

打开的文件是:3,buf长度是23OPEN_MAX获取成功,其值是102400mydup返回的文件是:3hello, mydup for dup2!

可见测试的buf成功通过获取的文件描述符写入到了标准输出中,至此测试完毕。


0 0
原创粉丝点击