操作系统-实验报告-文件管理.pdf
昆明理工大学信息工程与自动化学院学生实验报告昆明理工大学信息工程与自动化学院学生实验报告 201201201201学年学年 第第 二二学期学期 课程名称:操作系统课程名称:操作系统开课实验室:开课实验室:年年月月日日年级、年级、专业、专业、班班实验项目名称实验项目名称教教师师评评教师签名:教师签名:学号学号文件管理文件管理成绩成绩指导教师指导教师语语年年月月日日一、实验目的实验目的用 C 或 C+语言编写和调试一个简单的文件系统,模拟文件管理的基本功能。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。二、实验原理及基本技术路线图方框原理图二、实验原理及基本技术路线图方框原理图用 C 模拟实现文件系统的管理;要求设计一个多级目录结构的文件系统,能正确描述文件控制块,采用合理的外存分配方式,能实现基本的目录及文件的操作,包括创建、删除、重命名、复制、移动等功能,并对文件有一定的存取权限控制。功能设计功能设计:Helpdirexitcreate 文件名cdir 目录名read 文件名close文件名edit 文件名cd 目录名attr 文件名del 文件名rename 文件名显示命令帮助显示当前目录下的文件和文件夹退出系统创建文本文件创建文件夹读取一个文件最多可同时读取五个关闭一个文件编辑一个文件进子目录或者上级目录显示该文件的属性删除文件重命名-1-编辑功能流程图编辑功能流程图-2-删除文件流程图删除文件流程图创建文件流程图创建文件流程图核心算法:bool Format(void);/格式化bool install(void);/装载虚拟硬盘的数据void login(void);/用户登陆-3-void showMenu(void);/显示功能菜单bool onAction(void);/用户选择功能并执行void createFile(string str);/创建文件bool read(string str);/读取文件void editFile(string str);/编辑文件void Delete(string str);/删除一个文件数据结构:始地址/*inode 结构体*/struct inodeunsigned short di_tag;/*inode 标识*/*关联文件数,当为 0 时表示删除文件,如一个目录至少包含两个文件:.和.*/const unsigned int ACCOUNT_NUM=10;/用户数量/*-常变量-*/const unsigned int BLOCK_SIZE=512;/块长const unsigned int DATA_BLOCK_NUM=512;/数据块数量const unsigned int DINODE_START=4*BLOCK_SIZE;/inode 起始位置const unsigned int DINODE_SIZE=512;const unsigned int DINODE_NUM=32;/inode 大小/inode 数量const unsigned int DATASTART=(2+DINODE_NUM)*BLOCK_SIZE;/数据区 的开unsigned short di_number;unsigned short di_mode;/*存取模式:0 为目录,1 为文件*/unsigned short di_userID;/*当前 inode 所属用户 0 为根目录 ID,一次下去是管理员目-4-录、用户目录*/unsigned short di_access;/*访问权限 0 为不允许普通用户访问(公共目录),1 为允许普通用户访问*/;unsigned short di_size;/*文件大小,目录没有大小,值为 0*/unsigned short di_ctime;/*创建时间*/unsigned short di_mtime;/*最后一次修改时间*/unsigned short di_blockDATA_BLOCK_NUM;/*数据块块地址编号*/*超级块*/struct super_block;/*账户信息*/struct user;/*文件/目录结构*/struct directory-5-unsigned short s_inodes_count;/*文件系统中 inode 的总数*/unsigned short s_blocks_count;/*数据块总数*/unsigned short s_r_blocks_count;/*保留块总数*/unsigned short s_free_blocks_count;/空闲块总数unsigned short s_free_inodes_count;/*空闲的 inode 总数*/unsigned short s_log_block_size;/*block 的大小*/unsigned short user_id;/用户 IDunsigned short user_access;/权限string username;string password;/用户名/密码;string name;/*目录名*/unsigned short d_ino;/*目录号*/三、所用仪器、材料设备名称、型号、规格等三、所用仪器、材料设备名称、型号、规格等。电脑一台四、实验方法、步骤四、实验方法、步骤#include#include#include#includestruct OpenFileTablelongoffset;char file_name10;long int file_start;long int file_length;struct FCB_Blockintflag;/打开文件表数据结构/当前文件读写指针/文件名数组/文件起始块号/文件长度字节/FCB 数据结构/标志,-1 表示未用,1 表示文件用-6-char file_name10;/文件名数组long int file_date;/文件建立日期long int file_time;/文件建立时间;struct Super_Block/超级块数据结构,文件系统的分区信息,存放在 0#物理块中unsigned long int fs_totalsize;/整个分区的总磁盘物理块数unsigned long int fs_freesize;/分区的所有空闲磁盘物理块数unsigned int fs_blocksize;/文件系统的物理块大小字节unsigned int fs_fat_start;/FAT的起始磁盘物理块号unsigned int fs_fat_size;/FAT占用的磁盘物理块数unsigned int fs_dir_start;/根目录的起始磁盘物理块号unsigned int fs_dir_size;/根目录占用的磁盘物理块数unsigned int fs_data_start;/数据区起始磁盘物理块号unsigned long int fs_data_size;/数据区的磁盘物理块数long int file_start;/文件起始块号long int file_length;/文件长度字节;const char DiskName=FileSys.dat;/磁盘文件名char rw_buffer512;/读写使用的缓冲区struct FCB_Block filefcb130;/读写目录使用的数据结构-7-struct Super_Block FsSupBlk;/读写超级块使用的数据结构long int fat_buffer5000;/读写 FAT使用的缓冲区,为简化在系统启动时全部装入内存,0 为空闲struct OpenFileTable OFT16;/打开文件表,当前只使用 OFT0unsigned int block_size;/物理块大小字节unsigned long int total_disk_size;/磁盘总容量物理块数unsigned int total_dir_size;/目录占有的物理块数unsigned int total_fat_size;/FAT占有的物理块数long int find_fcb;/记录读 FCB 块的次数FILE*fsPtr;/模拟磁盘的文件指针/*磁盘块的申请*/unsigned long int Get_Block(unsigned long int count)/分配 count 个物理快,返回首块指针,其它已经连接unsigned long int tmp,firstblk,tmpcount;unsigned long int i;int flag=1;if(count FsSupBlk.fs_freesize)-8-printf(=没有足够磁盘容量,不能分配!=n);return 0;tmpcount=0;for(i=FsSupBlk.fs_data_start;iFsSupBlk.fs_totalsize)printf(=超出磁盘容量,不能读!=n);return;count+;i=j;fread(buf,512,1,fsPtr);-10-return;/*写磁盘块*/void Write_Block(unsigned long int addr,char*buf)fseek(fsPtr,FsSupBlk.fs_blocksize*addr,SEEK_SET);if(addrFsSupBlk.fs_totalsize)printf(=超出磁盘容量,不能写!=n);return;fwrite(buf,512,1,fsPtr);/*格式化磁盘*/void Real_Format()unsigned long int bcount;return;long int fatval,i;/更改系统超级块信息char*c;FsSupBlk.fs_totalsize=total_disk_size;FsSupBlk.fs_blocksize=block_size;FsSupBlk.fs_dir_start=1;FsSupBlk.fs_dir_size=total_dir_size;FsSupBlk.fs_fat_start=total_dir_size+1;-11-FsSupBlk.fs_fat_size=total_fat_size;FsSupBlk.fs_data_start=FsSupBlk.fs_fat_start+FsSupBlk.fs_fat_size;FsSupBlk.fs_data_sizeFsSupBlk.fs_fat_size-1;FsSupBlk.fs_freesize=FsSupBlk.fs_data_size;/初始化 FAT/初始化目录for(i=0;i128;i+)filefcbi.flag=-1;/为-1 表示 FCB 未使用fseek(fsPtr,512L,SEEK_SET);fwrite(&filefcb0,sizeof(struct FCB_Block),128,fsPtr);=FsSupBlk.fs_totalsize-FsSupBlk.fs_dir_size-fatval=FsSupBlk.fs_fat_start*512;fseek(fsPtr,fatval,SEEK_SET);/定位文件指针bcount=FsSupBlk.fs_fat_size+FsSupBlk.fs_dir_size+1;for(i=0;ibcount;i+)fat_bufferi=-1;/标记已经使用的磁盘数据块,即 FAT区、目录区和启动区-12-for(;iFsSupBlk.fs_totalsize;i+)fat_bufferi=0;/为 0 表示为空的物理快fwrite(&fat_buffer0,sizeof(long int),FsSupBlk.fs_totalsize,fsPtr);/初始化数据区for(i=0;i512;i+)rw_bufferi=;/缓冲区清空for(i=FsSupBlk.fs_data_start;iFsSupBlk.fs_totalsize;i+)Write_Block(i,rw_buffer);/缓冲区写入第 i 块/*新建系统磁盘文件*/void Create_Disk()/建立磁盘文件total=total_disk_size;for(i=0;itotal;i+)/建立大小为 total 的磁盘文件-13-long int i;unsigned long int total;fsPtr=fopen(DiskName,wb+);if(fsPtr=NULL)printf(不能建立磁盘所需的文件!n);exit(0);fwrite(rw_buffer,512,1,fsPtr);fclose(fsPtr);fsPtr=fopen(DiskName,rb+);Real_Format();return;/*读写系统超级块信息*/void Read_Boot()/读取磁盘超级块数据信息rewind(fsPtr);void FileBoot()/超级块数据信息存盘rewind(fsPtr);fread(&FsSupBlk,sizeof(struct Super_Block),1,fsPtr);return;fwrite(&FsSupBlk,sizeof(struct Super_Block),1,fsPtr);return;-14-/*FAT操作*/void LoadFat()/装载全部 FAT到内存fseek(fsPtr,FsSupBlk.fs_fat_start*512,SEEK_SET);void SaveFat()/FAT到文件 FAT区/*显示超级块信息*/void boot_dis()printf(FsSupBlk.fs_totalsize=%ldn,FsSupBlk.fs_totalsize);printf(FsSupBlk.fs_blocksize=%dn,FsSupBlk.fs_blocksize);printf(FsSupBlk.fs_dir_start=%dn,FsSupBlk.fs_dir_start);printf(FsSupBlk.fs_dir_size=%dn,FsSupBlk.fs_dir_size);-15-fread(fat_buffer,sizeof(long int),FsSupBlk.fs_totalsize,fsPtr);return;fseek(fsPtr,FsSupBlk.fs_fat_start*512,SEEK_SET);fwrite(fat_buffer,sizeof(long int),FsSupBlk.fs_totalsize,fsPtr);return;printf(FsSupBlk.fs_fat_start=%dn,FsSupBlk.fs_fat_start);printf(FsSupBlk.fs_fat_size=%dn,FsSupBlk.fs_fat_size);printf(FsSupBlk.fs_data_start=%dn,FsSupBlk.fs_data_start);printf(FsSupBlk.fs_data_size=%ldn,FsSupBlk.fs_data_size);printf(FsSupBlk.fs_freesize=%ldn,FsSupBlk.fs_freesize);/*系统初始化*/void Sys_Init()/初始化Read_Boot();/boot_dis();fsPtr=fopen(DiskName,rb+);if(fsPtr=NULL)Create_Disk();LoadFat();/*显示操作*/void dir()/显示目录下的文件int i,countFile=0;return;char str16;long int n,pos_dir,pos_fat;-16-pos_dir=FsSupBlk.fs_dir_start*512;pos_fat=FsSupBlk.fs_fat_start*512;fseek(fsPtr,pos_dir,SEEK_SET);while(ftell(fsPtr)pos_fat)fread(&filefcb0,sizeof(struct FCB_Block),16,fsPtr);coutendl;for(i=0;i16;i+)if(filefcbi.flag=1)/文件占有countFile+;n=filefcbi.file_length;printf(%-15s%15d bytesn,filefcbi.file_name,file,n);/*查找文件*/查找文件,文件存在返回当前 FCB 数组下标,否则返回-1-17-coutendl;printf(总共有%d 个文件n,countFile);printf(系统总共有%ld 个物理块可用nn,FsSupBlk.fs_freesize);int Find_File(char*filename)int i;long int pos_dir,pos_fat;pos_dir=FsSupBlk.fs_dir_start*512;pos_fat=FsSupBlk.fs_fat_start*512;find_fcb=0;fseek(fsPtr,pos_dir,SEEK_SET);while(ftell(fsPtr)pos_fat)find_fcb+;fread(&filefcb0,sizeof(struct FCB_Block),16,fsPtr);for(i=0;i16;i+)if(filefcbi.flag!=-1)if(strcmp(filename,filefcbi.file_name)=0)return i;/文件存在return-1;/*创建文件*/void create(char*fname,long int num)/在当前目录下创建一个名字为 str 的文件,长度为 numint i,j;/true 表示没有与该名字重名的文件int tempnode;-18-long int pos_dir,getnum=0;unsigned long int blkcount;blkcount=num/512+1;/计算需要的物理块if(FsSupBlk.fs_freesize blkcount)/磁盘没有足够空间/建立文件的处理if(tempnode!=-1)/表示文件存在 printf(n 文件已经存在,不需要建立!nn);return;tempnode=Find_File(fname);printf(n 磁盘没有足够空间,不能建立!nn);return;pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize;fseek(fsPtr,pos_dir,SEEK_SET);/定位到目录区for(i=0;iFsSupBlk.fs_dir_size;i+)/Read_Block(i+FsSupBlk.fs_dir_start,(char*)filefcb);fread(&filefcb0,sizeof(struct FCB_Block),16,fsPtr);-19-for(j=0;j16;j+)if(filefcbj.flag=-1)/找到空目录项/分配空间,标记 FCB 数据项,并将 FCB 写磁盘getnum=Get_Block(blkcount);if(getnum=-1)printf(不能分配存储空间 n);return;filefcbj.file_start=getnum;filefcbj.flag=1;filefcbj.file_length=num;strcpy(filefcbj.file_name,fname);/filefcb.file_time=/filefcb.file_date=/改变磁盘 FCB 值pos_dir=pos_dir+sizeof(struct FCB_Block)*(i*16+j);fseek(fsPtr,pos_dir,SEEK_SET);/定位到目录区的 FCB 项fwrite(&filefcbj,sizeof(struct FCB_Block),1,fsPtr);/Write_Block(i+FsSupBlk.fs_dir_start,(char*)filefcb);printf(文件占用了%d 个物理块n,blkcount);printf(系统还有%ld 个物理块可用nn,FsSupBlk.fs_freesize);return;-20-/没有 FCB 项,不能建立文件cout当前没有足够的目录区,不能建立文件!endl;return;/*格式化*/void format()char ch;coutch;if(ch=y|ch=Y)/*删除文件操作*/void del(char*fname)Real_Format();printf(n Format Successful!nn);long int tempnode;long int pos_dir;-21-/删除文件的处理tempnode=Find_File(fname);if(tempnode=-1)/表示文件不存在 printf(n 文件不存在,不能删除!nn);return;Put_Block(filefcbtempnode.file_start);/释放文件存储空间filefcbtempnode.flag=-1;/标记 FCB 项可用/修改的 FCB 项写回磁盘pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize+(find_fcb-1)*16+tempnode)*sizeof(struct FCB_Block);/*写文件*/void write(char*fname,int num)/写文件,仅实现在文件尾部填加内容,并限制在 512 个字节内int tempnode;int i,j,x;-22-fseek(fsPtr,pos_dir,SEEK_SET);/定位到目录区fwrite(&filefcbtempnode,sizeof(struct FCB_Block),1,fsPtr);return;int rescount;long int pos_dir;rescount=filefcbtempnode.file_length%FsSupBlk.fs_blocksize;char*string=new char num;/申请空间for(i=0;i 512)tempnode=Find_File(fname);if(tempnode=-1)/表示文件不存在/写文件的处理printf(n 文件不存在,不能写!nn);return;printf(n 不能写大于 512 字节的数据!nn);return;cinstringi;if(num FsSupBlk.fs_blocksize-rescount)if(FsSupBlk.fs_freesize1)-23-printf(n 文件系统没有足够空间,不能写!nn);return;for(j=filefcbtempnode.file_start;fat_bufferj!=-1;j=fat_bufferj);Read_Block(j,rw_buffer);if(num=FsSupBlk.fs_blocksize-rescount)elsefor(i=0;inum;i+)rw_bufferrescount+i=stringi;Write_Block(j,rw_buffer);for(i=0;iFsSupBlk.fs_blocksize-rescount;i+)rw_bufferrescount+i=stringi;Write_Block(j,rw_buffer);fat_bufferj=Get_Block(1);j=fat_bufferj;for(x=0;xFsSupBlk.fs_blocksize;x+)rw_bufferx=;for(x=0;xnum-(FsSupBlk.fs_blocksize-rescount);x+)rw_bufferx=stringi+x;Write_Block(j,rw_buffer);/delete string;-24-/修改 FCB 项并写回磁盘filefcbtempnode.file_length+=num;/增加文件的长度pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize+(find_fcb-1)*16+tempnode)*sizeof(struct FCB_Block);fseek(fsPtr,pos_dir,SEEK_SET);/定位到目录区fwrite(&filefcbtempnode,sizeof(struct FCB_Block),1,fsPtr);cin.ignore(10000,n);/清除输入流缓冲区void copyFcbtoOft(int fcbpos)OFT0.offset=0;strcpy(OFT0.file_name,filefcbfcbpos.file_name);coutendl=写文件完成!=filefcbtempnode.file_length)/读的数据超出文件范围 printf(n 超出文件范围,不能读!nn);return;/读文件的处理printf(n=n);stblknum=start/FsSupBlk.fs_blocksize+1;/起始物理块offset=start%FsSupBlk.fs_blocksize;/起始物理块的偏移量for(i=filefcbtempnode.file_start,j=1;jfilefcbtempnode.file_length)count=filefcbtempnode.file_length-start;Read_Block(i,rw_buffer);if(start+countfilefcbtempnode.file_length)count=filefcbtempnode.file_length-start;if(count=FsSupBlk.fs_blocksize-offset)else-26-for(j=0;jcount;j+)coutrw_bufferj+offset;for(j=0;jFsSupBlk.fs_blocksize-offset;j+)coutrw_bufferj+offset;dspnum=(count-(FsSupBlk.fs_blocksize-offset)/FsSupBlk.fs_blocksize+1;for(j=0;jdspnum-1;j+)/*显示帮助*/void display_help()-27-i=fat_bufferi;Read_Block(i,rw_buffer);x=(count-(FsSupBlk.fs_blocksize-offset)%FsSupBlk.fs_blocksize;for(j=0;jx;j+)coutrw_bufferx;coutendl=读文件完成!=endl;return;i=fat_bufferi;Read_Block(i,rw_buffer);for(x=0;xFsSupBlk.fs_blocksize;x+)coutrw_bufferx;printf(写文件wf filename size n);printf(读文件rf filename start size n);printf(删除文件df filename n);printf(建立文件cf filename size n);printf(显示文件dir n);printf(磁盘格式化format n);printf(退出文件系统quit nn);/*命令解释*/void CmdShell()/全部命令的解释执行过程-28-int j;int parameter;/记录命令行参数个数int len;/输入的命令行长度char string50;/输入的命令行字符串char*str4;/分解出的命令行参数bool flag;/标志coutn输入 help 查看所有命令endl);/输出系统提示符gets(string);len=strlen(string);/命令行信息的解析过程for(parameter=0,flag=true,j=0;j0)cout命令错误!endl;total_disk_size=4096;/磁盘总容量为 4096 块total_dir_size=16;/目录占有的物理块数为 16 块Sys_Init();/初始化磁盘系统CmdShell();/命令解释过程total_fat_size=32;/FAT占有的物理块数为 32 块-31-五、实验过程原始记录五、实验过程原始记录(数据、图表、计算等数据、图表、计算等)-32-六、实验结果、分析和结论误差分析与数据处理、成果总结等。其中,绘制曲线图六、实验结果、分析和结论误差分析与数据处理、成果总结等。其中,绘制曲线图时必须用计算纸时必须用计算纸通过这次实验,我知道了文件管理的任务是对用户文件和系统文件进行管理,方便用户的使用,并保证文件的安全性。文件管理的主要目标是提高外存储空间的利用率,并能有助于提高文件系统的工作速度,还有让我知道了文件目录中为了实现文件的按名存取,每个文件应该具有一定文件名与之对应。文件的类型有系统文件、用户文件、库文件还让我学到了旋转调度采用的是延迟时间最短者优先算法,旋转调度总是对先到达磁头位置上的扇区进行信息传送操作,假设访问的扇区号相同,则应分多次进行旋转调度。同时还让我知道了磁道的驱动调度算法还有移臂调度,移臂调度中的算法有先来先服务调度算法、最短寻道时间优先调度算法、扫描算法。先来先服务调度算法只需对访问磁道的作业排队。新来的访问者排在队尾,始终从队首取出访问磁盘,直到队列为空。最短寻道时间优先调度算法,需要为请求访问磁盘的作业设置一个队列,随着当前磁道的改变,不断计算后续访问者与当前磁道的距离,让距离最的访问者访问磁盘。当前磁盘为最新访问的磁道。扫描算法需要为访问者设置两个队列,根据磁头的移动方向,能先访问的访问者由近及远排队,背离磁头移动方向者叶由近及远排为另一队。先按磁头移动方向队列调度访问者访问磁盘,当该方向没有访问者时,再改变方向,选择另一个访问者队列访问磁盘。-33-