实验四 Linux的文件处理.docx
《实验四 Linux的文件处理.docx》由会员分享,可在线阅读,更多相关《实验四 Linux的文件处理.docx(20页珍藏版)》请在冰豆网上搜索。
![实验四 Linux的文件处理.docx](https://file1.bdocx.com/fileroot1/2023-8/7/240cd6d6-9a91-451d-84f1-08b34d7b4e21/240cd6d6-9a91-451d-84f1-08b34d7b4e211.gif)
实验四Linux的文件处理
实验四Linux的文件处理
1.目的要求
(1)学习和掌握gcc等Linux的开发调试环境。
(2)学习并掌握Linux的文件操作。
(3)编写并实现“学生管理系统”程序。
2.实验内容
(1)文件底层系统调用实验
●使用vi将程序清单4-1和4-2的程序输入,并在当前目录下创建文件“file.in”和文件“file.out”,尽可能的使文件“file.in”大一些。
●利用gcc分别编译这两个程序,写出编译命令和执行结果;如果不成功,尝试利用gdb调试。
编译命令:
gcc-oyunxing4_1.c
运行结果:
编译命令:
gcc-oyunxing4_2.c
运行结果:
●仔细观察这两个程序,比较标准C的文件操作和Linux的系统调用open、read、write等的使用区别。
标准C的文件操作:
是带有缓冲池的文件操作,同样的文件,读取时只需一次性。
Linux的系统调用:
直接调用底层函数,里面的while((nread=read(in,&c,sizeof(c)))>0)语句,是循环调用read函数,即访问一个数据边调用底层函数,这样会增加内外模式切换,增加负担。
●按照说明重新修改程序4-2,并使用time命令察看程序执行的时间效率上有何区别。
注意:
time中real代表程序实际运行时间
User中代表用户态运行时间
Sys中代表内核态运行时间
模拟系统调用:
命令:
time./yunxing
结果:
模拟缓冲区调用:
命令:
time./yunxing
结果:
论断:
带有缓冲区的调用会比系统调用节省时间。
●输入、编译并运行程序4-3和4-4,写出执行结果,并比较他们fseek和lseek在使用方法上的异同。
4_3:
其中hole.File内容:
4_4:
Hole.file内容:
结论:
就能容上并无差异。
(2)目录信息的单层浏览
●使用vi将程序清单4-5和4-6程序输入。
●利用gcc分别编译这两个程序,写出编译命令和执行结果;如果不成功,尝试利用gdb调试。
命令:
gcc-oyunxing4_5.c
结果:
命令:
gcc-oyunxing4_6.c
结果:
●仔细观察这两个程序,比较它们的区别。
区别:
都是事先查询显示路径下的目录下的文件。
前者:
不方便操作,类似于系统的直接调用,不为应用层熟悉的方法,而且路径不灵活
后者:
把目录的操作封装成了函数,这样封锁繁杂的细节,应用层没必要知道怎么实现,只需知道怎么用,方便了应用层,可移植性大
(3)目录信息的完整浏览
●使用vi将程序清单4-7和4-8程序输入。
●利用gcc分别编译这两个程序,写出编译命令和执行结果;如果不成功,尝试利用gdb调试。
命令:
gcc-oyunxing4_7.c
结果:
命令:
gcc-oyunxing4_8c
结果:
●仔细阅读、比较这两个程序,并写出目录浏览的算法描述。
算法是递归搜索目录下的文件,主要是递归
(4)mmap、msync和munmap的使用
●使用vi将程序清单4-9程序输入。
●利用gcc编译程序,写出编译命令和执行结果;如果不成功,尝试利用gdb调试。
命令:
gcc-oyunxing4_9.c
结果:
●仔细阅读程序,并画出程序流程图。
用fseekfreadfwrite函数改变结构体43的值为143
对结构体每个数据项赋值并写入文件
定义结构体,文件
用mmap映射虚拟内存
用msync回写入文件
用munmap释放虚拟内存
虚拟内存图如下:
(5)学习并分别使用标准C的文件操作函数和Linux的系统调用创建一个对学生基本信息进行操作(插入、修改和删除)的C程序,学生基本信息以结构体的形式存储在文件stu.info中。
structstu_info的定义如下:
structstu_info{
charstu_num[12];
charname[10];
shortintsex;/*0为女生,1为男生*/
charmobile_phone[12];
};
3.主要仪器设备及软件
(1)硬件:
计算机、网络
(2)软件:
VMWareworkstation、RedHat9.0
4.附录:
程序清单
(1)程序清单4-1
#include
#include
intmain(void)
{
charc;
FILE*in,*out;
if((in=fopen("file.in","r"))==NULL)
{
perror("fileopenerror!
");
exit(0);
}
out=fopen("file.out","w");
while((c=fgetc(in))!
=EOF)
fputc(c,out);
fclose(in);
fclose(out);
}
(2)程序清单4-2
#include
#include
#include
intmain()
{
//charblock[1024];
charc;
intin,out;
intnread;
in=open("file.in",O_RDONLY);
out=open("file.out",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
//将注释打开,并将两条语句的后一句注释掉,重新编译执行。
//while((nread=read(in,block,sizeof(block)))>0)
while((nread=read(in,&c,sizeof(c)))>0)
//write(out,block,nread);
write(out,&c,nread);
close(in);
close(out);
}
(3)程序清单4-3
#include
#include
#include
#include
#include
charbuf1[]="abcdefghij";
charbuf2[]="ABCDEFGHIJ";
voiderr_exit(char*err_s)
{
perror(err_s);
exit
(1);
}
intmain(void)
{
FILE*fp;
if((fp=fopen("hole.file","w"))==NULL)
err_exit("fileopenfail!
");
if(fwrite(buf1,sizeof(buf1),1,fp)!
=1)
err_exit("filewritebuf1error!
");
if(fseek(fp,40,SEEK_SET)==-1)
err_exit("fseekerror!
");
if(fwrite(buf2,strlen(buf2),1,fp)!
=1)
err_exit("filewritebuf2error!
");
fclose(fp);
}
(4)程序清单4-4
#include
#include
#include
#include
#include
charbuf1[]="abcdefghij";
charbuf2[]="ABCDEFGHIJ";
voiderr_exit(char*err_s)
{
perror(err_s);
exit
(1);
}
intmain(void)
{
intfd;
if((fd=open("hole.file",O_WRONLY|O_CREAT/*|O_APPEND,0644*/))==-1)
err_exit("fileopenfail!
");
if(write(fd,buf1,10)!
=10)
err_exit("filewritebuf1error!
");
if(lseek(fd,40,SEEK_SET)==-1)
err_exit("lseekerror!
");
if(write(fd,buf2,10)!
=10)
err_exit("filewritebuf2error!
");
}
(5)程序清单4-5
#include
#include
#include
intmain()
{
DIR*pDir=opendir(“MyDirectory”);
structdirent*pDirent;
structstatvStat;
if(pDir==NULL)
{
printf(“Can’topenthedirectory\”MyDirectory\”);
return1;
}
while((pDirent=readdir(pDir))!
=NULL)
{
lstat(pDirent->d_name,&vStat);
if(S_ISDIR(vStat.st_mode))
printf(“Directory:
%s\n”,pDirent->d_name);
else
printf(“File:
%s\n”,pDirent->d_name);
}
closedir(pDir);
return0;
}
(6)程序清单4-6
#include
#include
#include
intprintDir(char*path)
{
DIR*pDir=opendir(path);
structdirent*pDirent;
structstatvStat;
if(pDir==NULL)
{
printf(“Can’topenthedirectory:
%s”,path);
return-1;
}
while((pDirent=readdir(pDir))!
=NULL)
{
lstat(pDirent->d_name,&vStat);
if(S_ISDIR(vStat.st_mode))
printf(“Directory:
%s\n”,pDirent->d_name);
else
printf(“File:
%s\n”,pDirent->d_name);
}
closedir(pDir);
return0;
}
intmain()
{
char*dirPath;
printf(“pleaseinputbrowsedir’spath:
”);
scanf(“%s”,dirPath);
if(printDir(dirPath)==0)
return0;
else
return-1;
}
(7)程序清单4-7
/*Westartwiththeappropriateheadersandthenafunction,printdir,
whichprintsoutthecurrentdirectory.
Itwillrecurseforsubdirectories,usingthedepthparameterisusedforindentation.*/
#include
#include
#include
#include
#include
voidprintdir(char*dir,intdepth)
{
DIR*dp;
structdirent*entry;//定义目录结构体
structstatstatbuf;//文件属性结构体
if((dp=opendir(dir))==NULL){
fprintf(stderr,"cannotopendirectory:
%s\n",dir);
return;
}
chdir(dir);//改变工作目录
while((entry=readdir(dp))!
=NULL){
lstat(entry->d_name,&statbuf);//读取符号文件文件属性
if(S_ISDIR(statbuf.st_mode)){
/*Foundadirectory,butignore.and..*/
if(strcmp(".",entry->d_name)==0||
strcmp("..",entry->d_name)==0)
continue;
printf("%*s%s/\n",depth,"",entry->d_name);
/*Recurseatanewindentlevel*/
printdir(entry->d_name,depth+4);
}
elseprintf("%*s%s\n",depth,"",entry->d_name);
}
chdir("..");//返回
closedir(dp);
}
/*Nowwemoveontothemainfunction.*/
intmain()
{
printf("Directoryscanof/home:
\n");
printdir("/home",0);
printf("done.\n");
exit(0);
}
(8)程序清单4-8
/*Westartwiththeappropriateheadersandthenafunction,printdir,
whichprintsoutthecurrentdirectory.
Itwillrecurseforsubdirectories,usingthedepthparameterisusedforindentation.*/
#include
#include
#include
#include
#include
voidprintdir(char*dir,intdepth)
{
DIR*dp;
structdirent*entry;
structstatstatbuf;
if((dp=opendir(dir))==NULL){
fprintf(stderr,"cannotopendirectory:
%s\n",dir);
return;
}
chdir(dir);
while((entry=readdir(dp))!
=NULL){
lstat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)){
if(strcmp(".",entry->d_name)==0||
strcmp("..",entry->d_name)==0)
continue;
printf("%*s%s/\n",depth,"",entry->d_name);
printdir(entry->d_name,depth+4);
}
elseprintf("%*s%s\n",depth,"",entry->d_name);
}
chdir("..");
closedir(dp);
}
/*Nowwemoveontothemainfunction.*/
intmain(intargc,char*argv[])
{
char*topdir,pwd[2]=".";
if(argc!
=2)
topdir=pwd;
else
topdir=argv[1];
printf("Directoryscanof%s\n",topdir);
printdir(topdir,0);
printf("done.\n");
exit(0);
}
(9)程序清单4-9
/*WestartbydefiningaRECORDstructure
andthencreateNRECORDSversionseachrecordingtheirnumber.
Theseareappendedtothefilerecords.dat.*/
#include
#include
#include
#include
typedefstruct{
intinteger;
charstring[24];
}RECORD;
#defineNRECORDS(100)
intmain()
{
RECORDrecord,*mapped;
inti,f;
FILE*fp;
fp=fopen("records.dat","w+");/可写方式打开
for(i=0;irecord.integer=i;
sprintf(record.string,"RECORD-%d",i);//把整数I转换成字符串保存在record.string
fwrite(&record,sizeof(record),1,fp);//写入一个record的记录
}
fclose(fp);
/*Wenowchangetheintegervalueofrecord43to143
andwritethistothe43rdrecord'sstring.*/
fp=fopen("records.dat","r+");/可读方式打开
fseek(fp,43*sizeof(record),SEEK_SET);
fread(&record,sizeof(record),1,fp);
record.integer=143;
sprintf(record.string,"RECORD-%d",record.integer);
fseek(fp,43*sizeof(record),SEEK_SET);
fwrite(&record,sizeof(record),1,fp);
fclose(fp);//用fseekfreadfwrite函数改变值
/*Wenowmaptherecordsintomemory
andaccessthe43rdrecordinordertochangetheintegerto243
(andupdatetherecordstring),againusingmemorymapping.*/
f=open("records.dat",O_RDWR);//文件描述符
mapped=(RECORD*)mmap(0,NRECORDS*sizeof(record),
PROT_READ|PROT_WRITE,MAP_SHARED,f,0);
mapped[43].integer=243;
sprintf(mapped[43].string,"RECORD-%d",mapped[43].integer);
msync((void*)mapped,NRECORDS*sizeof(record),MS_ASYNC);//立即写入文件
munmap((void*)mapped,NRECORDS*sizeof(record));//解除映射
close(f);
exit(0);