练习题 4.5 分析程序 testseek.c 执行后,infile 文件的内容是什么,并运行验证。
/* testseek.c代码*/
#include "wrapper.h"
int main() {
chars1[6], s2[6];
int fd;
fd = open("infile" , O_RDWR, 0);
lseek(fd,10, SEEK_SET);
read(fd, s1 , 5);
s1[5]='\0';
printf("读出的内容是:%s\n",s1);
strcpy(s2, "12345");
lseek(fd,-5, SEEK_CUR);
write(fd , s2 , 5 );
Close(fd); exit (0);
}
编译、执行该程序:$ cat infile
ABCDEFGHIJKLMNOPQRST
$ gcc -o testseek testseek.c -L. -lwrapper
$ ./testlseek
读出的内容是:KLMNO
答:infile文件内容是“ABCDEFGHIJ12345PQRST ”
编程题 4.6 先创建测试文件 infile,其内容为"abcdefghijklmnopqrstuvwxyz";写一个程序,
在文件末尾追加一个指定字符’#’,在开始位置写入字符’^’,在指定位置(20)写入字符’&;请问程
序执行后文件 infile 的内容是什么?
#include "wrapper.h"
int main() {
int fd;
fd = open("infile" , O_RDWR, 0);
lseek(fd,0,SEEK_END);
write(fd,"#",1);
lseek(fd,0,SEEK_SET);
write(fd,"^",1);
lseek(fd,20,SEEK_SET);
write(fd,"&",1);
Close(fd);
exit (0);
}
编程题 4.7 编写一个程序,创建一个大小为 100MB 的大文件。
#include "wrapper.h"
int main() {
int out = Open( "file.out", O_WRONLY|O_CREAT|O_TRUNC,0666 );
lseek(out,100*1024*1024 - 1,SEEK_SET); //将文件的指针移动到指定位置
write(out," ",1);//随便写一个数据
close(out);
exit (0);
}
程序分析 4.8 分析以下程序执行后,文件 data 的大小是多少?
int main()
{
int fd, loc1, loc2;
char ch;
fd=open("data",O_WRONLY|O_CREAT|O_TRUNC,0777);
lseek(fd,12345678,SEEK_SET);
write(fd,&ch,1);
close(fd);
}
文件data 大小12345679
编程练习 4.12 编写程序,把下列变量的值写入文件 data1,然后读回显示。
unsigned char a = 128;
unsigned short c = 32700;
unsigned char ar[5] = {129,254,131,112,178};
计算这些变量占用内存容量,要求文件大小不多于变量占用的内存容量。
#include "wrapper.h"
int main() {
unsigned char a = 128;
unsigned short c = 32700;
unsigned char ar[5] = {129,254,131,112,178};
unsigned char ra;
unsigned short rc;
unsigned char rar[5];
int fd1 = Open( "file.out", O_WRONLY|O_CREAT|O_TRUNC,0666 );
write(fd1,(void*)&a,sizeof(unsigned char));
write(fd1,(void*)&c,sizeof(unsigned short));
write(fd1,(void*)ar,5 * sizeof(unsigned char));
close(fd1);
int fd2 = Open( "file.out", O_RDONLY,0666 );
read(fd2,(void*)&ra,sizeof(unsigned char));
read(fd2,(void*)&rc,sizeof(unsigned short));
read(fd2,(void*)rar,5 * sizeof(unsigned char));
printf("unsigned char a = %d\n",ra);
printf("unsigned short b = %u\n",rc);
printf("unsigned char ar[5] = {");
for(int i = 0; i < 5; i++)
printf("%d,",rar[i]);
printf("}\n");
close(fd2);
exit (0);
}
程序阅读4.15 假设文件 a.txt 和 b.txt 都存在,有以下一段代码:
int fd1,fd2,fd3,fd4;
fd1=open(“a.txt”,O_RDONLY,0);
fd2=open(“b.txt”,O_WRONLY,0);
fd3=dup(fd1);
fd4=dup2(fd2,0);
请给出该段代码执行后 fd1、fd2、fd3、fd4 的值。
fd1 = 3, fd2 = 4, fd3 = 3, fd4 = 0.
4.34 编写程序Cat.c,实现命令cat功能,演示文本文件内容,如:当执行"./Cat /etc/passwd" 时,在终端显示文件/etc/passwd的内容。
#include <stdio.h>
int main(int argc, char *argv[]) {
int read_ret;
if(argc < 2){
printf("ERROR\n");
return -1;
}
FILE *fp = fopen(argv[1], "r");
if(fp == NULL) {
printf("ERROR\n");
return -1;
}
while(1){
read_ret = fgetc(fp);
if(feof(fp)){
printf("\n");
break;
}
fputc(read_ret,stdout);
}
}
4.50 在 Linux 环境下,调用库函数 gettimeday 测量一个代码段的执行时间,请写一个程
序测量一次 read 和一次 fread 函数调用所需的执行时间,并对测量结果给出解释。提示:调
用 gettimeofday 函数可获得微秒级计时。
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/time.h>
int main()
{
int fd1;
FILE *fp;
char buf;
struct timeval time_start;
struct timeval time_end;
fd1 = open("test.txt",O_RDONLY);
fp = fopen("file.txt", "r");
gettimeofday(&time_start,NULL);
read(fd1,&buf,1);
gettimeofday(&time_end,NULL);
double us = (time_end.tv_usec - time_start.tv_usec) + (time_end.tv_sec - time_start.tv_sec) * 1000000;
printf("read = %lfus\n",us);
gettimeofday(&time_start,NULL);
fread(&buf, 1, 1, fp);
gettimeofday(&time_end,NULL);
us = (time_end.tv_usec - time_start.tv_usec) + (time_end.tv_sec - time_start.tv_sec) * 1000000;
printf("fread = %lfus\n",us);
close(0);
}
调用read 函数快一点,虽然fread会替我们做缓存,减少了实际出现的系统调用,但是调用一次还是read函数快,因为实际上调用fread最后还是用了read做真正的写入文件系统工作。
补充:
Explain the purpose of the open() and close() operations.
open() 实现文件打开,但是实际上是将要打开的文件转换为一个文件描述符,并且返回描述符数字。执行时候系统首先检查该文件的v_node是否存在,若不存在,则先为其创建其v_node,将文件的属性从外存读入v-node;创建其文件对象(file), 设置读写方式、读写位置、v-node指针,访问计数器置为1;然后,在进程的描述符表中找到索引号最小的空闲表项,在其中填入文件表表项的指针,返回描述符表项的索引号。若存在,仅将文件v-node的引用计数i_count加1。
close()实现文件关闭,调用close函数关闭某个文件时,系统会检查v-node的引用计数是否大于1,如果大于1,只需将计数值减1,仅当关闭其v-node的i_count成员为1的文件时,才销毁其v-node对象。