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 = ;
int n = ;
int top = ;
int stack[MAXN]; if((filedes2 > OPEN_MAX) || (filedes2 < )) {
printf("invalid filedes2!n");
return EXIT_FAIL;
} if(filedes == filedes2) {
return filedes2;
} while((n = dup(filedes)) < filedes2) {
if(n == -) {
printf("System can not make a filedes!n");
return EXIT_FAIL;
}
stack[top++] = n;
} close(filedes2); if(dup(filedes) == -) {
printf("dup function error!n");
return EXIT_FAIL;
} for(i = ; i < top; ++i) {
close(stack[i]);
} return filedes2;
} int main(int argc, char *argv[])
{
int filedes, filedes2; if(argc != ) {
printf("Parameter error!n");
return EXIT_FAIL;
} filedes = open(argv[], O_RDWR);
if(filedes == -) {
printf("Error! System cannot open %sn", argv[]);
return EXIT_FAIL;
} filedes2 = atoi(argv[]);
if(dup2_func(filedes, filedes2) != EXIT_FAIL) {
write(filedes2, "test", sizeof("test"));
} return ;
}

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

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

 
 
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。

文件IO 练习题的更多相关文章

  1. JAVA 基础编程练习题50 【程序 50 文件 IO】

    50 [程序 50 文件 IO] 题目:有五个学生,每个学生有 3 门课的成绩,从键盘输入以上数据(包括学生号,姓名,三门课成绩), 计算出平均成绩,将原有的数据和计算出的平均分数存放在磁盘文件&qu ...

  2. 标准io与文件io

    A: 代码重复: 语句块1: while(判断) { 语句块2: 语句块1: } 上面可以改写为: while(1) { 语句块1: if(判断) break: 语句块2: } B: 标准IO和文件I ...

  3. 文件IO函数和标准IO库的区别

    摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...

  4. 转 漫谈linux文件IO

    在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用 ...

  5. (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  6. Java文件IO操作应该抛弃File拥抱Paths和Files

    Java7中文件IO发生了很大的变化,专门引入了很多新的类: import java.nio.file.DirectoryStream;import java.nio.file.FileSystem; ...

  7. Java 文件IO续

    文件IO续 File类    用来将文件和文件夹封装成对象 方便对文件和文件夹的属性信息进行操作    File对象可以作为参数传递给流的构造函数 Demo1 File的构造方法 public cla ...

  8. Java 文件IO

    文件IO Java IO    IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都在IO包中    按操作数据分为 字节流和字符流        字符流的 ...

  9. 文件IO和标准IO

    2015.2.26 星期四,阴天 今天的内容主要是文件IO man 手册的分册: man -f open 查看那些分册中有openman 1 -- 普通的命令程序man 2 -- 系统调用man 3 ...

随机推荐

  1. Java多线程初学者指南(12):使用Synchronized块同步变量

    我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特性的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...

  2. requirejs学习博客址分享

    1. http://blog.jobbole.com/30046/ 2. http://www.requirejs.cn/ 3. http://www.ruanyifeng.com/blog/2012 ...

  3. NCPC 2012 Bread Sorting

    逆序对数的应用: 逆序对数的写法有,二分,树状数组,分治: 学习一下: 树状数组版: 代码: #include<cstdio> #include<cstring> #inclu ...

  4. 修改sphinx最大输出记录数

    修改sphinx最大输出记录数 归纳如下: Sphinx的查询默认最大记录数是:1000,而我们想更改这个数值.就需要更改三个地方. 1是更改sphinx.conf配置文件的:max_matches ...

  5. DZ真是各种强大

    近期对论坛做了大装修,非常享受这个过程. 真是着迷了,这个装修工程让我接连几天几乎到了废寝忘食的地步. 终于告一段落,又想起来折腾,因为对之前的文库系统感觉种种别扭. 没有空调,没有风扇,居然忙到夜里 ...

  6. Android调用MediaScanner进行新产生的媒体文件扫描

    有时候,我们拍了一张图片或录制了一段视频,图库应用默认没有将这些新产生的文件识别出来所以打开图库或视频播放器发现没有找到这些文件,需要调用MediaScanner扫描一下才会出来.从FFMPEG中找了 ...

  7. Learning WCF Chapter2 Data Contracts

    A data contract describes how CLR types map to XSD schema definitions. Data contracts are the prefer ...

  8. 三招搞挂Mysql(转)

    一.产生大量的undo日志 众所周知,InnoDB是一个支持MVCC的存储引擎,为了支持MVCC,InnoDB需要保存undo日志,以便对用户提供记录的历史版本.如果我们开启一个事务,反复地更新一条记 ...

  9. Hadoop RPC源码阅读-交互协议

    Hadoop版本Hadoop2.6 RPC主要分为3个部分:(1)交互协议(2)客户端 (3)服务端 (1)交互协议 协议:把某些接口和接口中的方法称为协议,客户端和服务端只要实现这些接口中的方法就可 ...

  10. Centos5.5内核升级

    当前版本linux-2.6.18-194.el5PAE目标版本linux-2.6.35.9内核升级步骤: 1.查看当前内核版本 uname –a¥ Linux localhost.localdomai ...