[APUE] 第三章部分习题
来源:互联网 发布:社会主义 知乎 编辑:程序博客网 时间:2024/05/16 18:41
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>#defineMAXN4096#defineEXIT_SUCC0#define EXIT_FAIL-1int 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 %s\n", argv[1]); return EXIT_FAIL; } filedes2 = atoi(argv[2]); if(dup2_func(filedes, filedes2) != EXIT_FAIL) { write(filedes2, "test", sizeof("test")); } return 0;}
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。
3.6 如果使用添加标志打开一个文件以便读、写,能否仍用lseek在任一位置开始读?能否用lseek更新文件中任一部分的数据?
由于linux系统还没安装好,先在windows下面试试:
#include <stdio.h>int main(){int i = 0, j = 6;int offset = 3;FILE *pf;pf = fopen("test.txt", "at+");//54646545606fseek(pf, offset, 0);fscanf(pf, "%d", &i);printf("%d\n", i);//输出46545606 fseek(pf, offset, 0);fprintf(pf, "%d", j);fclose(pf);//546465456066return 0;}
代码以at+模式打开文件test.txt,此时文件内容为54646545606,然后使用fseek()将文件偏移量设置为距开始位置offset个字节,然后读取一个整数,输出46545606,说明能够使用fseek随机读取,然后再用fseek()将文件偏移量设置为距现在位置offset个字节,应该到倒数第五个数字,然后使用fprintf()输出一个整数,最后的文件内容为546465456066,说明输出操作还是在文件尾,也就是说fprintf()前的fseek()操作并没有对输出操作产生影响。
小结:如果在打开文件时设置了append标志,那么打开文件后,文件的位置属性还是在文件头,此时,可以使用fseek(lseek应该也类似吧)在任一位置进行读,但是,写文件的话,只能在文件尾。因此,append标志只是影响了写文件操作,而且,并不影响文件位置。可以猜想,如果设置了该标志,当写文件时,首先将文件位置置于文件尾,然后进行写操作,最后将文件位置改为之前的值。
- [APUE] 第三章部分习题
- APUE第三章3.2习题分析
- 《APUE》第三章笔记(4)及习题3-2
- APUE 2 - 第三章文件I/O学习-习题
- 王爽 汇编语言 第三章 部分习题练习
- [APUE] 第四章习题解答
- APUE-第四章-习题笔记
- APUE第三章
- APUE 第三章
- Apue第三章
- apue第三章习题3.2 编写dup2功能相同的函数,要求不调用fcntl函数
- 【算法导论(第三版)】第二章部分习题代码
- 【算法导论(第三版)】第四章部分习题代码
- 《Unix/linux编程实践教程》第三章部分习题
- 《组合数学引论》第三章部分习题解答
- apue第三章(1)
- apue第三章(2)
- APUE 学习笔记(第三章)
- mysql自动执行EVENT事件
- tar.bz2 && .tar.xz 解压命令
- java中的IO整理(转)
- hadoop&hive优化
- 云计算(十三)- Offline Edits Viewer Guide
- [APUE] 第三章部分习题
- java运行命令解释
- C++内存管理详解
- Clojure 学习入门(13)—— binding
- Redis的安装配置介绍<转>
- 游戏行业成功基本与程序猿无关
- Strom Topology执行分析:worker数,Bolt实例数,executor数,task数
- 从表里删除行
- TOJ 4303