收藏 分销(赏)

大型试验.doc

上传人:快乐****生活 文档编号:2462449 上传时间:2024-05-30 格式:DOC 页数:48 大小:213.51KB
下载 相关 举报
大型试验.doc_第1页
第1页 / 共48页
大型试验.doc_第2页
第2页 / 共48页
大型试验.doc_第3页
第3页 / 共48页
大型试验.doc_第4页
第4页 / 共48页
大型试验.doc_第5页
第5页 / 共48页
点击查看更多>>
资源描述

1、Unix文件系统模拟实验报告一实验任务和说明这次实验是操作系统大型实验,要完成的任务是模拟unix操作系统中的文件系统功能。在终端界面上用户可以象unix的shell命令一样输入一些命令,如输入ls 显示文件目录,chmod改变文件权限,chown改变文件拥有者,chgrp改变文件所属组,chnam改变文件名,pwd显示当前目录,cd改变当前目录,mkdir创建目录,rmdir删除目录,mk创建文件 ,cp文件拷贝,rm删除文件,cat显示文件内容,login切换用户,passwd修改用户口令 等功能。在后台,要实现混合索引式文件结构,包括用空闲结点号栈管理空闲结点和成组链接发管理空闲盘块。二

2、实验需求分析、设计思路和总体方案1基本思路:用一个文件(disk.txt)模拟一个物理硬盘, 通过对该文件的一系列操作,模拟UNIX文件系统中的文件操作。2理磁盘块的设计:卷盘块数等于100块,每个磁盘块512字节,磁盘块之间用/n隔开,总共是514字节。0#表示超块,1#-10#放索引结点,每个索引结点占64字节,共80个索引结点。初始化是存在根目录root,占用了0#结点和11#盘块。3空闲磁盘块:采用成组链接法管理。每组10块,12#-99#分为9组,每组的最后一个磁盘块里存放下一组的磁盘号信息。最后一组只有8块,加上0作为结束标志。在超块中用一个一维数组(10个元素)作为空闲磁盘块栈。

3、放入第一组盘块。4空闲I结点:采用混合索引式文件结构。索引结点结构中文件物理地址为六项:四个直接块号,一个一次间址,一个两次间址,其中一次间址和两次间址中一个磁盘块中存放16个磁盘号 。在超块中也用一维数组(80个元素)作为空闲I结点栈,与空闲磁盘块管理不同的是这里不用采用成组链接法,这一维数组中存放所有I结点编号,而且一直保持同一大小秩序。根目录占0#索引结点,由于根目录不会删改,是一直占0#索引结点,所以我并未按实验指导所说,把它写在超块里,不过写进去也无所谓的。5超块,I结点和目录结构的设计struct SUPERBLOCK/超块 int fistack80;/空闲结点号栈 setw(3

4、)*80 int fiptr;/空闲结点栈指针(还有多少个) setw(3) int fbstack10;/空闲盘块号栈 setw(3)*10 int fbptr;/空闲结点栈指针 setw(3) int inum;/空闲i结点总数 setw(3) int bnum;/空闲盘块总数 setw(3);struct INODE/i结点(64B) 已保证了每两个数据之间有空格隔开 int fsize;/文件大小 setw(6) int fbnum;/文件盘块数 setw(6) int addr4;/四个直接盘块号(0 512*4=2048) setw(3)*4 int addr1;/一个一次间址()

5、 setw(3) int addr2;/一个两次间址() setw(3) char owner6;/文件拥有者 setw(6) char group6;/文件所属组 setw(6) char mode11;/ 文件类别及存储权限 setw(12) char ctime9;/最近修改时间 setw(10);struct DIR/目录项(36B) char fname14;/文件名(当前目录) setw(15) (0 14) int index;/i结点号 setw(3) (15 17) char parfname14;/父目录名 setw(15) (18 32) int parindex;/父目

6、录i结点号 setw(3) (33 35);结点结构中的文件盘块数,目录项结构中的父目录名,父目录i结点号,其实可以不要,基本是不用到或是可以不用的,但是当我意识到时,程序已编得差不多了,为了避免牵一发而动全身,只好留着!6用户,密码和组我的用户组信息是存放在另一个文件(user.txt)中的。三各个主要功能模块(函数)的说明是程序的主函数模块主函数首先会根据控制文件control.txt的头一个位(初始化确定位)来确定是否进行初始化。如果初始化,那么将只有一个根目录。因为一旦初始化后,初始化确定位就会置为0,所以系统只会在第一次进入时初始化,以后都是在前面建立的文件结构上进行操作的。如果一定

7、要系统初始化时,可把control.txt的头一个位置为1,或者使用命令“reset”。进入系统时,当前路径是根目录。然后是登陆请求。登陆后,超块读入内存(由一个结构对象superblock模拟),进入命令解析层,对用户的不同命令执行不同的操作。退出系统前,把内存的超块再写回disk.txt。 是程序的所有全局变量、结构、函数声明的模块。也包括了所有要用到的系统库。 是定义有关超块、结点、盘块、目录项的底层操作函数的模块。1对结点的操作:int ialloc(void);申请一个i结点 返回结点号 否则返回-1。返回的是空闲结点号栈中最小的结点号,结点用完时返回-1,申请失败。void ifr

8、ee(int index);指定一个结点号,回收一个i结点。先清空结点,然后插入栈中合适位置(必须保持结点号的有序性)。void readinode(int index,INODE &inode);读指定的i结点( n#结点,读指针应定位到514+64*n (64B)+2*(n/8) )到INOE inode寄存 便于对同一结点的大量操作void writeinode(INODE inode,int index);把INODE inode写回指定的i结点2对盘块的操作;用的是成组链接法。(n#盘块 读指针应定位到514*n)int balloc(void);申请一个盘块 返回盘块号 否则返回-

9、1void bfree(int index);指定一个盘块号,回收一个盘块3对超块的操作;void readsuper(void);读超块到内存SUPERBLOCK superblock;void writesuper(void);内存SUPERBLOCK superblock;写回超块4对目录项的操作( n#目录项读指针应定位514*index+36*n )void readdir(INODE inode,int index,DIR &dir);读指定目录项进临时对象DIR dir;void writedir(INODE inode,DIR dir,int index);目录项对象DIR d

10、ir写到指定目录项 是定义初始化函数的模块其中包括了对用户组的初始化:定义三个用户adm,cnj和jtq,其中adm,cnj的组为adm,jtq的组为guest。用户的初始密码都为123。对超块的(0#盘块)初始化 、对根目录文件结点(0#结点)的初始化 、对数据盘块的初始化。定义了两个功能函数:1登陆 bool login(void); 要求输入用户信息,并判断是否合法。2改变用户密码 void changepassword(void); 改变当前用户的密码。6. file.h:定义了有关文件操作的四个函数1创建文件void mk(char *dirname,char *content);当

11、前目录下创建一个数据文件(规定目录文件只占1 4个盘块)。虽然不要求这个函数,但我觉得很有必要。而且,因为我使用了两个参数,前一个表示文件名,后一个表示文件内容,可以在文件拷贝里使用这个函数。2删除文件void rm(char *filename); 当前目录下删除指定数据文件3文件拷贝void cp(char*string); 给定一个路径,把那个文件拷贝到当前目录下。首先要使用dir.h里面根据路径找到目标的函数(find(char*string))找到对应文件,如果是数据文件的话,记录文件内容到一缓冲区,然后在当前目录下调用创建目录的函数,就完成了。4显示文件内容void cat(cha

12、r *filename); 显示当前目录下指定数据文件的内容。7. dir.h:定义两个底层函数1bool havesame(char *dirname,INODE inode,int &i,int &index2)判断对象inode指向的目录文件盘块中有无该名(dirname)的目录项存在着,有返回1无返回0。同时,有该目录项的话,则按引用调用的i为待删子目录目录项下标 index2为目录项中的待删子目录的结点号2bool find(char *string)根据路径找到指定文件或目录。需要注意的是,使用此函数时当前路径跟着改掉了,所以使用前必须保存当前路径。万一找不到目标的话,可以还原为当

13、前路径。定义了有关目录操作的四个功能函数, 1void mkdir(char *dirname)当前目录下创建目录(规定目录文件只占一个盘块。为了降低难度,已设定目录文件只占一个盘块。2void rmdir(char *dirname,int index)当前目录下删除目录。将要删除的目录可能非空。有两种策略:一、规定只能删除空目录。二、递归地将非空目录的所有子目录删除,让后再删除自己。第一种实现较简单,我使用了第二种策略。所以参数为 (子目录名,当前结点)。如果使用第一种策略的话,参数为只要子目录名就可以了。3void ls(void)显示当前结点的所有子目录4void cd(char *s

14、tring)改变当前目录。有四中处理过程: string为“.”切换到当前目录;为“.”切换到父目录 ;为“/”切换到根目录;如果为一路径的话,就调用bool find(char *string) 切换到指定目录。8. chsome.h:定义一个底层函数:bool havewpower(INODE inode)判断当前用户对指定的结点有无写权限定义四个功能函数:1void chmod(char *name)改变当前目录下指定文件的文件权限2void chown(char *name)改变当前目录下指定文件的文件拥有者(如拥有者在另一个组,那么组也要改掉)3void chgrp(char *na

15、me)改变当前目录下指定文件的文件所属组4void chnam(char *name)改变当前目录下指定文件的文件名 命令解析层函数模块。接受用户命令,执行不同的操作。四命令格式及运行结果一开始为登陆请求。可选用户为:adm cnj jtq 密码都是123登陆后在根目录1pwd 显示当前目录 2mksome 创建bin dev 等6个目录这是我自己为方便添加的功能, 2ls显示当前目录下所有子目录 3mkdir dirname创建目录 4mk filename创建数据文件 5rmdir dirname删除目录6cd . 切换当前目录 基本没用处cd . 切换到父目录 cd 子目录名 切换到子目

16、录 cd /切换到根目录cd 绝对路径 切换到指定目录 6cp 路径 把路径指定的文件拷贝到当前目录下7cat filename 显示当前目录下指定数据文件的内容 chmod name 改变当前目录下指定文件或目录的权限模式chown name 改变当前目录下指定文件或目录的拥有者chgrp name 改变当前目录下指定文件或目录的所属组 个人认为没用。可能是还不理解其用途。chnam name 改变当前目录下指定文件或目录的名字 12rm filename 删除当前目录下指定文件13login 当前用户注销新用户登陆 14reset 系统重置 既是把初始化函数执行一下15exit 安全退出系

17、统。 如果不是安全退出的话,超块不会写回内存。下次进入必须要系统重置五心得体会这次实验是有生以来写的最长的代码。多达1700行。至少花了本人一个半星期的时间。其中还包括两次通宵,n次夜班。写完后,自己都不敢相信自己写了那么多。很有成就感。嘎嘎其实,上课认真听了的话,从理论上理解UNIX文件系统并不难,最多是多看几遍书,多查查资料,难的是用代码去解决具体问题。以前编程是有具体算法的,就算不理解都能搞定。这次就不行了,只给出问题。那么,要编好程序,除了经验,就要求非常深的本质上的理解了。编程过程中碰到很多问题,例如文件流的操作。本来还以为对文件流懂得差不多了,这次实验又出现问题:1.单ios:ou

18、t摧毁原文件的问题。2.不能同时打开两个文件流的问题。等!都耗了不少时间才发现并纠正的。这次实验不仅让我大大加深了对操作系统这门课的理解,更重要的是提高了我编程序,特别是系统程序的能力!六C+源代码1. main.cpp#include head.h#include blockinodesuperblock.h#include initial.h#include userop.h#include file.h#include dir.h#include command.h#include chsome.h/void main() control.open(control.txt,ios:in

19、| ios:out | ios:nocreate); int i; controli; control.close(); if(i!=0)/不为0就初始化 initial(); control.open(control.txt,ios:in | ios:out | ios:nocreate); control.seekp(0); control0;/默认是上次基础上继续下去不用再初始化 control.close(); strcpy(curname,root);/当前目录文件名为root road0=0;/当前目录路径(存放从根目录到这里的结点号) num=1;/最后位roadnum-1为当前

20、目录文件i结点号 cout请登陆系统n; while( !login() )/登陆为止 coutwrong !n; cout login successendl; cout*Welcome auser0) int temp=superblock.fistack80-superblock.fiptr;/当前可用 superblock.fistack80-superblock.fiptr=-1; superblock.fiptr-; return temp; return -1;/void ifree(int index)/指定一个结点号,回收一个i结点 disk.open(disk.txt,io

21、s:in | ios:out | ios:nocreate );/清空结点 disk.seekp(514+64*index+2*(index/8); disksetw(64) ; disk.close(); for(int i=80-superblock.fiptr;i80;i+)/结点号找到合适位置插入空闲结点号栈 if(superblock.fistacki是记录盘块了 /是最后记录盘块最后号0(保留作栈底 分配不成功) if(temp=0) return -1; superblock.fbstack10-superblock.fbptr=-1; superblock.fbptr=0; /

22、盘块内容读入栈 for(int i=0;i10;i+) int id,num=0; disk.open(disk.txt,ios:in | ios:out | ios:nocreate );/先计算盘块内容个数num(最多10),最后盘块可能不到10个 disk.seekg(514*temp); for(int i=0;iid; num+; if(id=0) break; disk.seekg(514*temp);/盘块内容读入栈 for(int j=10-num;jid; superblock.fbstackj=id; superblock.fbptr=num; disk.close();

23、disk.open(disk.txt,ios:in | ios:out | ios:nocreate );/清空回收盘块 disk.seekp(514*temp); disksetw(512)盘块使用掉 superblock.fbstack10-superblock.fbptr=-1; superblock.fbptr-; return temp; /void bfree(int index)/指定一个盘块号,回收一个盘块 disk.open(disk.txt,ios:in | ios:out | ios:nocreate );/清空回收盘块 disk.seekp(514*index); di

24、sksetw(512) ; disk.close(); if(superblock.fbptr=10)/栈已满栈中内容记入回收盘块 栈清空 disk.open(disk.txt,ios:in | ios:out | ios:nocreate ); disk.seekp(514*index); for(int i=0;i10;i+) disksetw(3)superblock.fbstacki; superblock.fbstacki=-1; disk.close(); superblock.fbptr=0; /回收盘块压栈 superblock.fbstack10-superblock.fbp

25、tr-1=index; superblock.fbptr+;/void readsuper()/读超块到内存 disk.open(disk.txt,ios:in | ios:out | ios:nocreate); int i; for(i=0;isuperblock.fistacki; disksuperblock.fiptr;/空闲结点号栈指针 for(i=0;isuperblock.fbstacki; disksuperblock.fbptr;/空闲盘块号栈指针 disksuperblock.inum;/空闲结点号总数 disksuperblock.bnum;/空闲盘块号总数 disk.

26、close();/void writesuper()/内存写回超块 disk.open(disk.txt,ios:in | ios:out | ios:nocreate); int i; for(i=0;i80;i+)/写空闲结点号栈 disksetw(3)superblock.fistacki; disksetw(3)superblock.fiptr;/空闲结点号栈指针 for(i=0;i10;i+)/写空闲盘块号栈 disksetw(3)superblock.fbstacki; disksetw(3)superblock.fbptr;/空闲盘块号栈指针 disksetw(3)superbl

27、ock.inum;/空闲结点号总数 disksetw(3)inode.fsize;/文件大小 diskinode.fbnum;/文件盘块数= 目录文件为1数据文件14都有 for(int i=0;iinode.addri; diskinode.addr1;/一个一次间址()= 不使用了 diskinode.addr2;/一个两次间址()= 不使用了 diskinode.owner;/文件拥有者 diskinode.group;/文件所属组 diskinode.mode;/ 文件类别及存储权限 diskinode.ctime;/最近修改时间 disk.close();/void writeino

28、de(INODE inode,int index)/把INODE inode写回指定的i结点 disk.open(disk.txt,ios:in | ios:out | ios:nocreate); disk.seekp(514+64*index+2*(index/8); disksetw(6)inode.fsize;/文件大小 disksetw(6) 目录文件为1数据文件14都有 for(int i=0;i4;i+)/四个直接盘块号 disksetw(3)inode.addri; disksetw(3) 不使用了 disksetw(3) 不使用了 disksetw(6)inode.owner;/文件拥有者 disksetw(6)inode.group;/文件所属组 disksetw(12)inode.mode;/ 文件类别及存储权限 disksetw(10)dir.fname; diskdir.index;

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 考试专区 > 中考

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服