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. C++程序的编写和实现

    C++程序的编写和实现 一个程序从编写到最后得到运行结果要经历以下一些步骤. 1. 用C++语言编写程序 用高级语言编写的程序称为“源程序”(source program).C++的源程序是以.cpp ...

  2. Spring 3整合Quartz 2实现定时任务一:常规整合 (基于maven构建)

    最近工作中需要用到定时任务的功能,虽然Spring3也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能也不够强大.在考虑之后,决定整合更为专业的Quartz来实现定时任务功能. 首先,当然是添加依 ...

  3. Discuz!X3.1 全新安装图文教程

    http://www.discuz.net/thread-3456887-1-1.html

  4. OSAL多任务资源分配机制

    转自OSAL多任务资源分配机制 一.概述      OSAL (Operating System Abstraction Layer),翻译为"操作系统抽象层". 个应用程序对象. ...

  5. 【POJ 2987】Firing (最小割-最大权闭合子图)

    裁员 [问题描述] 在一个公司里,老板发现,手下的员工很多都不务正业,真正干事员工的没几个,于是老板决定大裁员,每开除一个人,同时要将其下属一并开除,如果该下属还有下属,照斩不误.给出每个人的贡献值和 ...

  6. bower初接触

    之前从Steve Sanderson的博文Architecting large Single Page Applications with Knockout.js中学习了用Yeoman创建Knocko ...

  7. 转载:浅谈Java多线程的同步问题【很好我就留下来,多分共享】

    转载:http://www.cnblogs.com/phinecos/archive/2010/03/13/1684877.html#undefined 多线程的同步依靠的是对象锁机制,synchro ...

  8. 如何实现Android重启应用程序代码 ?

    Intent i = getBaseContext().getPackageManager()  .getLaunchIntentForPackage(getBaseContext().getPack ...

  9. bzoj1822

    显然是二分+最大流判定但比较烦的是判断线段和圆及其内部是否有公共点我的判断方法是错的,但是数据弱目前只知道推公式分类讨论,如果有简单的方法求教 ; type node=record flow,po,n ...

  10. Java序列化技术

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化? Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象 ...