UNIX环境高级编程———第三章习题
来源:互联网 发布:ubuntu控制台关机 编辑:程序博客网 时间:2024/05/18 03:43
1.当读/写磁盘文件时,本章中描述的函数确实是不带缓存机制的吗?
答:首先我们来说明缓存的:不带缓存的I/O和带缓存的I/O(标准I/O)
(1)不带缓存的I/O:数据——内核缓存区——磁盘(硬盘);只有系统调用;文件描述符
当进行读写操作时,数据直接进行系统调用(read,write),进入内核缓存区,然后等待内核缓存存满之后将数据写入到磁盘。
假如内核缓存区在缓存满10个字节就将数据写入到磁盘,假设我每次写入1个字节,那么我需要写入10次才能保证所有数据肯定被存入硬盘(此处假设开始时内核缓存区为0字节),也就是说我需要进行10次系统调用。
(2)带缓存的I/O :数据——用户缓存区——内核缓存区——磁盘(硬盘);系统调用[1]和函数库调用[2];数据流
当进行读写操作时,数据首先进行函数调用(fread,fwrite),进入到用户缓存区,然后等待用户缓存区存满了之后进行系统调用(write,read),进入到内核缓存区,等待内核缓存区存满之后将数据写入磁盘。
假设内核缓存区在缓存满10个字节就将数据写入到磁盘,用户缓存区写满5个就将数据写入到内核缓存区,那么我每次写1个字节,那么如果要将数据写入到磁盘,我至少需要写入10次,(此处假设开始时用户缓存区和内核缓存区为0个字节),2次10次函数调用,2次系统调用。
总结:就上面的例子进行比较,因为使用系统调用会影响系统的性能。与函数调用相比,系统调用时,Linux必须从运行用户代码切换到执行内核代码,然后再返回用户代码,所以系统调用的开销要比普通函数调用大一些。所以可想而知,带缓存的I/O要比不带缓存的I/O效率高很多。
然后我们来解答次题:
本章中的不带缓存的函数并不是不带缓存,只是不带用户缓存。
注释:
[1]系统调用:操作系统的主要功能是为管理硬件资源和为应用程序开发人员提供良好的环境来使应用程序具有更好的兼容性,为了达到这个目的,内核提供一系列具备预定功能的多内核函数,通过一组称为系统调用(system call)的接口呈现给用户。系统调用把应用程序的请求传给内核,调用相应的的内核函数完成所需的处理,将处理结果返回给应用程序。
[2]关于内核读写函数:http://blog.csdn.net/tommy_wxie/article/details/8194276
原文地址:http://blog.csdn.net/melanie327/article/details/8275909
2.编写一个与3.12中dup2功能相同的函数,要求不调用fcntl函数,并且有正确的报错(这个程序存在问题,求大家指出错误)
#include "apue.h"#include "unistd.h"int main(void){ int fd,fd2; if ((fd=open("/home/mocun/unix/chapter1/try",0)) < 0) /*获取try这个文件的描述符*/ err_quit("open error"); printf("fd is %d \n",fd); fd2 = dup3(fd,19);/*调用dup3将复制这个文件描述符为19*/ printf("succeed find the %d",fd2); close(fd2);}int dup3(int fd,int new_fd){ int i,a,index[100],tmpfd; if (fd == new_fd) /*判断19与文件本身是否相等*/ return fd; for (i = 0;new_fd != fd ;++ i) /*如果不相同,则使用dup不断的获取文件描述符,知道与19相等*/ { index[i] = fd; fd = dup(fd); } printf("find the fd %d:\n",fd); if (write(fd,"i try",10) < 0) /*为了检验是否正确,我尝试打开文件写入数据,但是失败,所以现在这个程序应该还是有问题的*/ err_sys("write error!"); for (a = 0;a <= i;++ a) close(index[a]); return fd;}3.假设一个进程执行下面的3个函数调用:
fd1 = open(path,oflags)
fd2 = dup(fd1)
fd3 = open(path,oflags)
(1)
fcntl作用于fd1来说, F_SETFD命令会影响哪一个文件描述符?F_SETFL呢?
(2)F_SETFD:只是修改文件描述符标志(文件描述符标志的解释:http://blog.csdn.net/lott_mocun/article/details/48791173http://)
(3)F-GETFD:只是修改文件状态标志(只读,只写,......等)
4.许多程序都包括下面的程序:
dup2(fd,0)
dup2(fd,1)
dup2(fd,2)
if (fd > 2)
close(fd);
为了说明if语句的必要性,假设if时1,画出每次调用dup2时3个描述符项及相应的文件表项的变化情况,然后再画出fd为3的情况。
5.在Bourne,Bourne_again shell 和 Korn shell 中,digital1>digital2表示要将描述符digital重定向之描述符digital2的同一文件。请说明下面两条命令的区别。
(1)./a.out > outfile 2>&1
因为shell命令是从左到右执行的,所以从左到右一次分析命令之间的关系,首先将标准输出(输出到shell屏幕)重定向为输出到outfile,即将./a.out的结果输入到outfile,然后将错误输出文件描述符2重定向为标准输出。结果是描述符1指向outfile的文件表项,描述符 2指向终端的文件表项
./a.out 2>&1 > outfile
首先将错误输出文件描述符2重定向为标准输出,然后将标准输出(输出到shell屏幕)重定向为输出到outfile,即将./a.out的结果输入到outfile。结果是描述符1指向outfile的文件表项,描述符 2指向终端的文件表项。
6.如果使用追加标志打开一个文件以便读写,能否仍用lseek在任意位置开始读?能否用lseek更新文件中任一部分的数据?请编写一段程序验证
答:这种情况之下,仍然可以用lseek和read函数读文件中任意一处的内容。但是 write函数在写数据之前会自动将文件位移量设置为文件尾,所以写文件时只能从文件尾开始,不能在任意位置。
编写的程序:
#include "apue.h"#include <fcntl.h>int main(void){ int fd; char buf1[20]; /*定义一个字符串用来读取文件中的字符*/ char buf2[10]="onetwothre";/*用来写入的字符串*/ if ((fd = open("/home/mocun/unix/chapter1/try",2|O_APPEND)) < 0)/*使用追加方式打开文件*/ printf("open error! \n"); if (lseek(fd,5,SEEK_SET) < 0) /*将文件的偏移量设置为5*/ printf("lseek error! \n"); if (read(fd,buf1,5) < 0) /*从偏移量为5处读出五个字符*/ printf("read error! \n"); else printf("read:%s",buf1);/*将读出的字读输出*/ if (write(fd,buf2,10) < 0) /*将字符串buf2写入文件*/ printf("write error! \n");}
文件的初始状态:
运行程序后:
shell输出结果:
- UNIX环境高级编程———第三章习题
- UNIX环境高级编程习题——第三章
- UNIX环境高级编程习题——第二章
- UNIX环境高级编程习题——第四章
- UNIX环境高级编程习题——第五章
- UNIX环境高级编程习题——第六章
- UNIX环境高级编程习题——第七章
- UNIX环境高级编程习题——第八章
- Unix环境高级编程 第三章习题答案
- unix环境高级编程第三章习题的一些拙见
- UNIX环境高级编程习题之第三章第二题
- UNIX环境高级编程——第三章
- UNIX环境高级编程习题——第一章
- Unix环境高级编程第三章习题2(转载修改)
- 《UNIX环境高级编程》学习笔记--第三章习题2参考答案
- <<UNIX环境高级编程>>学习总结——第三章:文件I/0
- UNIX环境高级编程——第三章-文件I/O
- UNIX环境高级编程第三章
- Android--记录和恢复listView滚动位置的3种方法 (20
- 如何在esxi 6上面套嵌运行虚拟机(kvm、xen、esxi6、vmware workstation、Qemu)
- 短信JAVA开发接口
- 笔试答题的时候,用什么笔最好
- nyoj745蚂蚁的难题(二)【dp】
- UNIX环境高级编程———第三章习题
- NSNotificationCenter(通知中心)
- 二叉树的数量
- Android像素单位的理解
- JVM内存模型
- 软件测试中就自动化测试是否终将能替代手动测试的讨论。
- uva 442
- FPGA实现排序
- iOS --- 使用NSURL的urlWithString时,尽量先对字符串进行UTF8转码