zoukankan      html  css  js  c++  java
  • 文件IO 练习题

    3.1 当读/写磁盘文件时,本章中描述的函数是否具有缓冲机制?请说明原因。

    3.1 所有的磁盘 I/O 都要经过内核的块缓冲区(也称为内核的缓冲区高速缓存),唯一例
        外的是对原始磁盘设备的 I/O,但是我们不考虑这种情况。Bach[1986]的第 3 章描述
        了这种缓冲区高速缓存的操作。既然 read 或 write 的数据都要被内核缓冲,那么术
        语“不带缓冲的 I/O”指的是用户的进程中对这两个函数不会自动缓冲,每次 read 或
        write 就要进行一次系统调用。
    3.2 编写一个与 3.12 节中 dup2 功能相同的函数,要求不调用 fcntl 函数,并且要有正确的出错处理。

    int dup2(int filedes, int filedes2); 将filedes2对应的打开文件置为filedes对应的打开文件,之后就可以使用filedes2操作filedes打开的文件。

    由于要复制一个文件描述符,而且不能使用fcntl(),那么,唯一能使用的就是dup()了:

    int dup(int filedes); 复制一个当前可用的最小的文件描述符,使它对应的打开文件是filedes对应的打开文件。

    这里采用的主要思想是:dup()返回的是当前可用的最小的文件描述符,那么就可以使用遍历,从dup(filedes)开始遍历,知道返回的文件描述符等于filedes2。

    下面介绍主要流程:

    当filedes2是无效文件描述符时,输出错误信息,那么什么样的是无效文件描述符呢?就是小于0或者大于进程可以打开的最大文件数时,文件描述符是无效的。

    然后就可以分为三种情况:

    filedes == filedes2: 直接返回filedes2

    filedes > filedes2: 关闭filedes2,再进行dup(filedes)返回值应该就是filedes

    filedes < filedes2: 从dup(filedes)开始遍历,直到返回值等于filedes2,然后关闭filedes2,再dup(filedes)返回值应该就是filedes

    后面两种情况可以结合一下,看看代码,代码参考了APUE习题 3.2 浅析

    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    #define    MAXN    4096
    #define    EXIT_SUCC    0
    #define EXIT_FAIL    -1
    
    int dup2_func(int filedes, int filedes2)
    {
        int i = 0;
        int n = 0;
        int top = 0;
        int stack[MAXN];
    
        if((filedes2 > OPEN_MAX) || (filedes2 < 0)) {
            printf("invalid filedes2!n");
            return EXIT_FAIL;
        }
    
        if(filedes == filedes2) {
            return filedes2;
        }
    
        while((n = dup(filedes)) < filedes2) {
            if(n == -1) {
                printf("System can not make a filedes!n");
                return EXIT_FAIL;
            }
            stack[top++] = n;
        }
    
        close(filedes2);
    
        if(dup(filedes) == -1) {
            printf("dup function error!n");
            return EXIT_FAIL;
        }
    
        for(i = 0; i < top; ++i) {
            close(stack[i]);
        }
    
        return filedes2;
    }
    
    int main(int argc, char *argv[])
    {
        int filedes, filedes2;
    
        if(argc != 3) {
            printf("Parameter error!n");
            return EXIT_FAIL;
        }
    
        filedes = open(argv[1], O_RDWR);
        if(filedes == -1) {
            printf("Error! System cannot open %sn", argv[1]);
            return EXIT_FAIL;
        }
    
        filedes2 = atoi(argv[2]);
        if(dup2_func(filedes, filedes2) != EXIT_FAIL) {
            write(filedes2, "test", sizeof("test"));
        }
    
        return 0;
    }

    假设一个进程执行下面的3个函数调用:
    fd1 = open(pathname, oflags);
    fd2 = dup(fd1)
    fd3 = open(pathname, oflags)

    要画出一个表图!
    我知道fd1和fd2会指向同一个文件表数据结构,但对于fd3这个就不知道怎么回事!看了一下结果,才明白,很有意思~

     
    dup 和open思考题 - ZZB - 青涯
     
    fd3会指向另一个文件表,但最终还是会指向与fd1同一个物理地址。
    fcntl作用于fd1来说,F_SETFD命令只影响fd1的文件描述符标志;F_SETFL作用于fd1时,则影响fd1和fd2指向的文件表项。
     

    3.4 在许多程序中都包含了下面一段代码:

    dup2(fd, 0);
    dup2(fd, 1);
    dup2(fd, 2);
    if(fd > 2)
        close(fd);

    请说明if语句的必要性。

    其实,首先可以看看,这几句话可以实现什么功能?

    三个函数将0, 1, 2指向的文件表项赋为fd指向的文件表项,因此,这三个函数起到文件重定向的作用,使对标准输入输出出错的操作定向到fd打开的文件。

    如果fd <= 2,也就是对三个标准的操作定向到其中一个的操作。

    如果fd > 2,也就是对三个标准的操作定向到fd打开的文件,此时就有4个文件描述符指向fd打开的文件。

    为什么要关闭fd呢?书上给的答案是:“这种情况下就需要关闭描述符3”。但没有说明为什么。

    如果不关闭fd会有什么问题吗?个人认为,已经有了三个标准的操作,此时就不需要fd了,而且如果fd再操作的话容易引起混乱,纯属个人见解。

    3.5 在Bourne shell、Bourne-again shell和Korn shell中,digit1 > &digit2表示要将描述符digit1重定向至描述符digit2的同一文件。请说明下面两条命令的区别。

    ./a.out  >  outfile  2>&1
    ./a.out  2&>1  > outfile

    从左往右看

    第一条命令:先将标准输出重定向到outfile,即1 > outfile,然后2>&1,将标准出错重定向到标准输出,由于标准输出已经重定向到outfile,因此,标准出错也重定向到outfile。

    第二条命令:先将标准出错重定向到标准输出,然后将标准输出重定向到标准输出重定向到outfile。

    结果是:

    第一条命令:标准输出和标准出错都定向到outfile。

    第二条命令:标准出错指向标准输出重定向之前的打开文件,标准输出定向到outfile。

  • 相关阅读:
    HPE Proliant DL380 GEN10服务器配置iLO 5/RAID/安装系统
    centos7安装oracle 11g
    服务器 swap分区使用率高的原因分析及增加swap空间
    mongodb操作记录
    为我的理想和执着的梦想继续前进!
    解决办法-HTTP 错误 401.3 未经授权:访问由于 ACL 对所请求资源的设置被拒绝。
    淘金归来:论坛如何显示IP
    2009年牛起来~~~
    通过.NET访问 Oracle数据库
    电脑小技巧 玩转电脑!
  • 原文地址:https://www.cnblogs.com/wuchanming/p/3958853.html
Copyright © 2011-2022 走看看