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. avalon中require的实现

    var plugins = { loader: function(builtin) { window.define = builtin ? innerRequire.define : otherDef ...

  2. 什么是xsi:type ???

    http://www.w3.org/2001/XMLSchema-instance http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.ecli ...

  3. 守望先锋overwatch美服外服设置方法

    打开:C:\Users\你的用户名\AppData\Roaming\Battle.net\Battle.net.config 替换为下方内容: { "Client": { &quo ...

  4. sublime 编译程序出错控制台打印PATH的解决办法

    找到sublime的安装目录 搜索 exec.py 打开找到这几句话193行左右或者搜索关键词path if "PATH" in merged_env: self.debug_te ...

  5. 关于django Models的个人理解和related_name的使用

    作为一个新人(刚刚大学还没有毕业就出来实习,可以说是真的什么都不知到,什么都要重新学,但是这样真的可以锻炼自己的意志力和能力).现在在公 司是前端和后端一起坐,所以要学的东西是真的多的让人想不到.在学 ...

  6. relink:在Linux/UNIX平台上relink Oracle软件(转)

    当操作系统升级后.操作系统打完补丁后.安装完Oracle补丁之后和relink过程中出现问题时,都会用到relink方法来保证Oracle软件的正常使用.本文介绍一下relink方法的使用.   1. ...

  7. zip压缩解压缩 项目icsharpcode-SharpZipLib-e012155

    大家可以到http://www.icsharpcode.net/opensource/sharpziplib/ 下载SharpZiplib的最新版本,支持Zip, GZip, BZip2 和Tar格式 ...

  8. warning: push.default is unset;

    git push warning questions This warning was introduced in Git 1.7.11 along with the simple style of ...

  9. c语言中%p指针

    %p与指针对应,是输出指针的地址 如: char * p="abc"; ...... printf("The address %p is %s", p, p); ...

  10. 修改mysql 数据库密码

    第1种︰使用 mysqladmin命令 shell>mysqladmin -u root password new_password 如果忘记了MySQL的root密码,可以用以下方法重新设置: ...