第一篇:操作系统课程设计之请求式面页管理
一、目的与要求
1、目的
近年来,由于大规模集成电路(LSI)和超大规模集成电路(VLSI)技术的发展,使存储器的容量不断扩大,价格大幅度下降。但从使用角度看,存储器的容量和成本总受到一定的限制。所以,提高存储器的效率始终是操作系统研究的重要课题之一。虚拟存储技术是用来扩大内存容量的一种重要方法。学生应独立地用高级语言编写几个常用的存储分配算法,并设计一个存储管理的模拟程序,对各种算法进行分析比较,评测其性能优劣,从而加深对这些算法的了解。
任务三采用最佳淘汰算法(OPT)实现,任务四采用最近最少使用页淘汰算法(LRU)实现。
2、要求
为了比较真实地模拟存储管理,可预先生成一个大致符合实际情况的指令地址流。然后模拟这样一种指令序列的执行来计算和分析各种算法的访问命中率。
二、示例
1、题目 本示例是采用页式分配存储管理方案,并通过分析计算不同页面淘汰算法情况下的访问命中率来比较各种算法的优劣。另外也考虑到改变页面大小和实际存储器容量对计算结果的影响,从而可为算则好的算法、合适的页面尺寸和实存容量提供依据。
本程序是按下述原则生成指令序列的:(1)50%的指令是顺序执行的。
(2)25%的指令均匀散布在前地址部分。(3)25%的指令均匀散布在后地址部分。
示例中选用最佳淘汰算法(OPT)和最近最少使用页面淘汰算法(LRU)计算页面命中率。公式为
命中率1页面失效次数
页地址流长度假定虚存容量为32K,页面尺寸从1K至8K,实存容量从4页至32页。
2、算法与框图
(1)最佳淘汰算法(OPT)。这是一种理想的算法,可用来作为衡量其他算法优劣的依据,在实际系统中是难以实现的,因为它必须先知道指令的全部地址流。由于本示例中已预先生成了全部的指令地址流,故可计算出最佳命中率。
该算法的准则是淘汰已满页表中不再访问或是最迟访问的的页。这就要求将页表中的页逐个与后继指令访问的所有页比较,如后继指令不在访问该页,则把此页淘汰,不然得找出后继指令中最迟访问的页面淘汰。可见最佳淘汰算法要花费较长的运算时间。(2)最近最少使用页淘汰算法(LRU)。这是一种经常使用的方法,有各种不同的实施方案,这里采用的是不断调整页表链的方法,即总是淘汰页表链链首的页,而把新访问的页插入链尾。如果当前调用页已在页表内,则把它再次调整到链尾。这样就能保证最近使用的页,总是处于靠近链尾部分,而不常使用的页就移到链首,逐个被淘汰,在页表较大时,调整页表链的代价也是不小的。(3)程序框图如下图2所示。
产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产size=1assigned=4产产产产产产AlgAlg=OPT/LRU产OPTLRU产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产产 图2 计算页面命中率框图
3、程序运行结果格式(1)程序运行结果格式
THE VIRTUAL ADDRESS STREAM AS FOLLOWS: a[0] =16895
a[1]=16896
a[2]=16897
a[3]=16302 a[4]=25403
a[5]=13941
a[6]=13942
a[7]=8767 „„ „„ „„
A[252]=23583
a[253]=20265
a[254]=20266
a[255]=20267 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = The algorithm is:opt PAGE NUMBER WITH SIZE 1k FOR EACH ADDRESS IS: pageno[0]=17 pageno[1]=17
pageno[2]=17
pageno[3]=16 pageno[4]=25
pageno[5]=14
pageno[6]=14
pageno[7]=9 „„ „„ „„
pageno[252]=24
pageno[253]=20
pageno[254]=20
pageno[255]=20
vmsize=32k
pagesize=1k---------------------------page assigned
pages_in/total references 4
7.***E-1 6
7.***E-1 8
8.***E-1 10
8.***E-1 12
8.***E-1 14
9.***E-1 16
9.***E-1 18
9.***E-1 20
9.***E-1 22
9.***E-1 24
9.***E-1 26
9.***E-1 28
9.***E-1 30
9.***E-1 32
9.***E-1 PAGE NUMBER WITH SIZE 2k EACH ADDRESS IS: „„ „„ „„
PAGE NUMBER WITH SIZE 4k EACH ADDRESS IS: „„ „„ „„
PAGE NUMBER WITH SIZE 8k EACH ADDRESS IS: „„ „„ „„
End the result for opt ** ********************************************** the algorithm is lru „„ „„ „„同上
End the result for lru *********************************************(2)示例中使用的有关数据结构、常量和变量说明如下: length 被调试的指令地址流长度,可作为一个常量设定。called当前请求的页面号。
pagefault页面失效标志,如当前请求页called已在页表内,则置pagefault=false,否则为true。
table 页表。table[i]=j,表示虚存的第j页在实存的第i页中。
used当前被占用的实存页面数,可用来判断当前实存中是否有空闲页。(3)本程序启动后,屏幕上显示“the algorithm is:”,用户可选择最佳淘汰算法(打入“OPT”)或者最近最少使用淘汰算法(打入“LRU”)计算页面命中率。当然还可以加入各种其他的算法。
三、实习题
(1)编制和调试示例给出的请求页式存储管理程序,并使其投入运行。(2)增加1~2种已学过的淘汰算法,计算它们的页面访问命中率。试用各种算法的命中率加以比较分析。
提示:可选用FIFO方法,即先访问的页先淘汰,也可选用LRU方法中的其他方案。如在页表中设置标志位,按标志位值得变化来淘汰。也可用LFU方法,为页表中各页面设置访问计数器,淘汰访问频率最低的页(注意:当前访问的页不能淘汰)等等。
实验步骤与源程序 #include “iostream” #include “stdio.h” #include “stdlib.h” using namespace std;#define Max 30 //某进程调入内存中的最大页面数 #define Size 10 //系统为某进程分配的最大物理块数 void Init(int Block[],int m)//初始化物理块 { int i;for(i=0;i Block[i]=-1;} } void creat(int Page[],int n)//输入页面串引用号 { int i;for(i=0;i cin>>Page[i];} } void Init1(int Block1[],int m1){ int i;for(i=0;i Block1[i]=-1;} } void creat1(int Page[],int n1){ int i;for(i=0;i Page[i];} } void LRU(int Page[],int Block1[],int n1,int m1){ int i,j,max_stay=0,count=0;int get=-1,flag=-1,block_num=-1;int time[Size];for(i=0;i time[i]=0;} for(i=0;i { if(Block1[j]==-1) { get=j;//物理块j即将(/等待)驻入新页面 break; } } for(j=0;j { if(Block1[j]==Page[i])//物理块j中页面与当前期望调入内存的页面相同 { time[j]=0; flag=j; break; } } for(j=0;j { if(time[j]>max_stay) { max_stay=time[j]; block_num=j;//block_num标记当前序号物理块中页面驻留时间最久 } } if(flag==-1)//不存在相同页面 { if(get!=-1)//物理块即将(/等待)驻入新页面 { Block1[get]=Page[i];//存入页面 time[get]=0;//当前物理块重新计时 for(j=0;j<=get;j++)//已驻入页面的驻留时间加1 { time[j]++; } get=-1; } else //页面调度置换,序号block_num的物理块是驻留时间最久的 { Block1[block_num]=Page[i]; time[block_num]=0; for(j=0;j { time[j]++; } block_num=-1; max_stay=0; count++; } } else //待调入页面与序号flag的物理块中页面相同 { for(j=0;j { time[j]++; } flag=-1; } for(j=0;j { cout<<“ ”< } cout< } if(n1>m1) count=count+m1;cout<<“缺页中断次数为:”< { time[i]=0;} for(i=0;i { if(Block[j]==-1) { get=j; break; } } for(j=0;j { if(Block[j]==Page[i]) { flag=j; break; } } for(j=0;j { if(time[j]>max_stay) { max_stay=time[j]; block_num=j; } } if(flag==-1) { if(get!=-1) { Block[get]=Page[i]; time[get]=0; for(j=0;j<=get;j++) { time[j]++; } get=-1; } else { Block[block_num]=Page[i]; time[block_num]=0; for(j=0;j { time[j]++; } block_num=-1; max_stay=0; count++; } } else { for(j=0;j { time[j]++; } flag=-1; } for(j=0;j { cout<<“ ”< } cout< count=count+m;cout<<“缺页中断次数为:”< switch(t){ case '1':LRU(Page,Block1,n1,m1); continue;case '2':FIFO(Page,Block,n,m); continue;case '3':exit(0);} } } 测试数据与实验结果 图1 输入要分配的物理块数、页面总数、页面序列号 图2 LRU算法的实现 图3 FIFO算法的实现 4、小结 (1)编制评测各种算法性能的模拟程序是研制系统程序,尤其是操作系统所必须的。模拟的环境愈是真实,其结果愈是可靠,也就更有利于选择合适的方案。本实习虽属简单,但可作为一个尝试。 (2)注意正整数的范围只能从0„„32767,限制程序中的虚存尺寸为32K,实际如采用更大的虚存实存,更能说明问题。 页面置换算法理解比较容易,这次根据学号要求实现的是LRU和FIFO算法的实现。 其实这两种算法的程序编写比较容易,虽然不全是自己编写的,一部分是参考的网上的例题,但是通过对每一语句的理解,自己弄懂了整个程序的执行原理。但是,在编写过程中自己还是遇到了一些问题。 最大的一个问题就是两个算法的正确实现,在程序的编写时,两个程序是分开进行编写的,分别执行起来没有什么问题,但是把两个程序融合在一起后,却出现了问题,即在执行完成一个算法后再执行另外一个算法时,开始的数据是紧接着上次算法结果的数据进行实验的。这个问题困扰了我好长时间,直到现在还没有很好的解决掉,程序只能分别执行一次,如果再进行执行的话,就会出现问题。 自己的编程技术不好,程序编的也很繁琐,但是基本的要求已经实现了,希望这次的实验是自己动手的一个开始,自己应该更加努力,再接再厉。 四、思考题 (1)设计一个界地址存储管理的模拟系统,模拟界地址方式下存储区的分配和回收过程。 提示:必须设置一个内存分配表,按照分配表中有关信息实施存储区的分配,并不断根据存储区的分配和回收修改该表。算法有首次匹配法,循环首次匹配法和最佳匹配法等。可用各种方法的比较来充实实习内容。可使用碎片收集和复盖等技术。对分区的管理法可以是下面三种算法之一: 首次适应算法 循环首次适应算法 最佳适应算法 #include /*修改已分配区表*/ i=0;while(used_table[i].flag!=0&&i }/*主存分配函数结束*/ void reclaim(char J)/*回收作业名为J的作业所占主存空间*/ { int i,k,j,s,t;float S,L;/*寻找已分配表中对应登记项*/ s=0;while((used_table[s].flag!=J||used_table[s].flag==0)&&s for(i=1;i (2)自行设计或选用一种较为完善的内存管理方法,并加以实现。提示:设计一个段页式管理的模拟程序或通过一个实际系统的消化和分析,编制一个程序来模拟该系统。#include struct program { char name[30];long start;long length;struct program *next;}; struct space { long start;long length;struct space *next;}; void creat();void allot();void back();void callback(program *r);void sort(space *L);void sort(program *S);void display(space *L);void display(program *S); space *L;program *S; void creat(){ L=new space;space *p=new space;p->start=0;p->length=128;p->next=NULL;L->next=p;S=new program;S->next=NULL;} void allot(){ program *q;q=new program;cout<<“请输入进程名和占用空间大小:”< p->next->length-=q->length;if(p->next->length!=0)p->next->start+=q->length;else { if(p->next->next!=NULL)p->next=p->next->next;else { r->next=NULL;delete p->next;} } } display(L);display(S);} void back(){ char name[30];cout<<“输入要回收的进程名:”;cin>>name;program *p;p=S;while(p->next!=NULL){ if(strcmp(p->next->name, name)==0){ callback(p);return;} p=p->next;} if(p->next==NULL)cout<<“此进程不存在,内存回收失败”< { q->next=p->next;q->length=q->length+p->length+n;t->next=r->next;delete r;} else if(r->start+n==p->start)//下邻空 { p->start-=n;p->length+=n;t->next=r->next;delete r;} else if(q->start+q->length==r->start){ q->length+=n;t->next=r->next;delete r;} else { space *sp=new space;sp->start=r->start;sp->length=n;sp->next=L->next;L->next=sp;t->next=r->next;delete r;} cout<<“此进程内存回收完毕.”< length< length< { space *p=L->next, *q, *r;if(p!=NULL){ r=p->next;p->next=NULL;p=r;while(p!=NULL){ r=p->next;q=L;while(q->next!=NULL&&q->next->start start)q=q->next;p->next=q->next;q->next=p;p=r;} } } void sort(program *S)//链表排序 { program *p=S->next, *q, *r;if(p!=NULL){ r=p->next;p->next=NULL;p=r;while(p!=NULL){ r=p->next;q=S; 起始地址:“< start<<” 长 while(q->next!=NULL&&q->next->start start)q=q->next;p->next=q->next;q->next=p;p=r;} } } void main(){ creat();int a;cout<<“ 内存分配与回收模拟”< #include “stdio.h” #include “string.h” #include “malloc.h” #include “stdlib.h” #define MAX 1000 struct file/*普通文件的结构体*/ { //int type;//0无作用,当做一个空节点存在;1为记录型文件;2为执行文件 //前两个变量为文件的权限设置,1为允许操作,0为不允许操作 int write;//可写 int read;//可读 int length;//文件的长度 char ch[MAX];};typedef struct file File; typedef struct ffile/*定义文件类型的结构体*/ { int type;//1为文件夹; 2为文件; char name[20];//文件(夹)名字 int open;//文件打开标志,0为关,1为开 File iffile;//如果为文件时有的信息 struct ffile *parent;//指向上一级文件的指针 struct ffile *brother;//指向同级兄弟文件(夹)的指针 struct ffile *child;//指向下一级文件(夹)的指针 }Ffile;typedef Ffile *FFile; /*typedef struct Open/*记录打开文件的结构体 { char name[20];//记录打开文件(夹)的名字 FFile* add;//记录打开文件上一级文件地址的指针 }Open;*/ //全局变量 FFile user1;//用户1 FFile user2;//用户2 FFile copyf;//记录被复制文件(夹)的上一级文件地址 //Open openf[20];//记录打开文件的队列 FFile init(void)/*初始化,创建根结点*/ { FFile c;c=(Ffile*)malloc(sizeof(Ffile)); c->type=2;c->open=0;//c->iffile.type=2;c->iffile.write=1;c->iffile.read=1;c->iffile.length=0;strcpy(c->name,“file1”);c->parent=NULL;c->child=NULL;c->brother=NULL;strcpy(c->iffile.ch,“NULL”);return(c);} /*void initopen(){ int a,b;a=20;for(b=1;b<=a;b++){ openf[b].add=NULL;} }*/ //传递要显示文件的parent的地址 void show(FFile user)/*显示当前界面存在的文件*/ { user=user->child;if(user==NULL){ printf(“该文件内没有任何文件(夹)。n”);return;} printf(“n”);for(;user!=NULL;){ printf(“<%s”,user->name);if(user->type==2){ /*if(user->iffile.type==1) printf(“/记录型文件/”); else printf(“/执行文件/”);*/ printf(“/%dk”,user->iffile.length);} else { printf(“/文件夹”); } printf(“>n”); user=user->brother;} } void creatf(FFile user)/*创建文件 || 文件夹*/ { FFile parent;char ch[20];//FFile user0;//parent=(Ffile*)malloc(sizeof(Ffile));parent=user;printf(“输入要创建文件(夹)的名字:n”); scanf(“%s”,ch);if(user->child==NULL){ user->child=(Ffile*)malloc(sizeof(Ffile)); user=user->child;}else { user=user->child; for(;;) { if(user->type==0)//开端的空结点,用新结点覆盖 break; if(!strcmp(user->name,ch)) { printf(“错误:该文件名已经存在,文件(夹)创建失败!n”); return; } if(user->brother==NULL) { user->brother=(Ffile*)malloc(sizeof(Ffile)); user=user->brother; break; } user=user->brother; } } } //设置新文件(夹)的信息 strcpy(user->name,ch);printf(“选择创建对象:1文件夹; 2文件;n”);scanf(“%d”,&user->type);user->open=0;if(user->type==2)//添加文件信息 { //printf(“选择文件类型:1记录型文件;2执行文件;n”);//scanf(“%d”,&user->iffile.type);printf(“能否对文件进行读:0禁止;1允许;n”);scanf(“%d”,&user->iffile.read);printf(“能否对文件进行写:0禁止;1允许;n”);scanf(“%d”,&user->iffile.write);//printf(“设置文件大小(单位:K):n”);//scanf(“%d”,&user->iffile.length);user->iffile.length=0;strcpy(user->iffile.ch,“NULL”);} user->brother=NULL;user->child=NULL;user->parent=parent;printf(“文件创建成功!n”);void deletechildtree(FFile user)/*删除子树--结合deletefile();使用*/ { if(user->brother!=NULL)//从下到上,从右到左删除 { deletechildtree(user->brother);} if(user->child!=NULL){ deletechildtree(user->child);} if(user!=NULL){ free(user);} } void deletefile(FFile user,char ch[20])/*删除文件 || 文件夹*/ { FFile p,parent; int a;parent=user;if(user->child==NULL){ printf(“错误:删除失败,该目录下没有可删除的文件(夹)!n”);return;} user=user->child;p=user;for(a=1;;a++)//找出要删除文件的所在位置 { if(!strcmp(user->name,ch)) break;if(user->brother==NULL){ printf(“错误:删除失败,当前位置没有该文件!n”); return;} if(a>1) p=user;user=user->brother;} if(user->open==1)//判断文件的开关情况 { } printf(“错误:删除失败,选择文件处于打开状态!n”);return;if(p==user)//被删文件在文件队列的开头 { if(user->brother==NULL)//该文件队列只有有一个文件 { parent->child=NULL; if(user->child!=NULL)//删除的是文件(夹)子树 { deletechildtree(user);}else { free(user);//删除的是文件(夹)结点 } printf(“删除成功!n”);return;} //文件队列有多个文件 p=user->brother; } parent->child=p;p->parent=parent;if(user->child!=NULL){ deletechildtree(user);}else { free(user);} printf(“删除成功!n”);return;else//被删文件不在队列开头 { if(user->brother==NULL)//被删文件在文件队列最末尾 { p->brother=NULL;if(user->child!=NULL){ deletechildtree(user);}else { free(user);} } printf(“删除成功!n”);return; //被删文件在文件队列中间 p->brother=user->brother; if(user->child!=NULL) { deletechildtree(user); } else { free(user); } } printf(“删除成功!n”);} FFile openfolder(FFile user)/*打开文件夹*/ { } //int a,b;//a=0;/*if(user->child==NULL){ user->child=(Ffile*)malloc(sizeof(Ffile));user->child->type=0;user->child->brother=NULL;user->child->parent=user;user->child->child=NULL; } /*for(b=1;b<=20;b++){ if(openf[b].add!=NULL) a++;} if(a==20){ printf(“错误:打开列表溢出!”);return(user);} for(b=1;;b++){ if(openf[b].add==NULL) break;}*/ user->open=1;//设置文件为打开 //strcpy(openf[b].name,user->name);//openf[b].add=user;printf(“文件夹打开成功。n”);return(user);//返回被打开的文件夹的地址 void openfile(FFile user)/*打开普通文件*/ { if(user->open==1){ printf(“错误:打开失败,此文件已经被打开!n”); return;} user->open=1;printf(“普通文件打开成功!n”);} FFile openff(FFile user)/*打开文件(夹)*/ { char ch[20];FFile parent; int a;printf(“选择要打开的文件名:n”);scanf(“%s”,ch); parent=user;if(user->child==NULL){ printf(“错误:打开失败,该目录下没有可打开的文件(夹)!n”);return(parent);} user=user->child;for(a=1;;a++)//找出要打开文件的所在位置 { if(!strcmp(user->name,ch)) break;if(user->brother==NULL){ printf(“错误:打开失败,当前位置没有该文件!n”); return(parent);} user=user->brother;} if(user->type==1){ printf(“开始打开文件夹。。n”);user=openfolder(user);} else if(user->type==2){ printf(“开始打开普通文件。。n”); openfile(user); user=user->parent;} return(user);} void closefile(FFile user)/*关闭普通文件*/ { char ch[20];int a;printf(“选择要打开的文件名:n”);scanf(“%s”,ch);if(user->child==NULL){ printf(“错误:关闭失败,该目录下没有可关闭的文件!n”);return;} user=user->child;for(a=1;;a++)//找出要关闭文件的所在位置 { if(!strcmp(user->name,ch)) break;if(user->brother==NULL){ printf(“错误:关闭失败,当前位置没有该文件!n”); return;} user=user->brother;} if(user->open==0){ printf(“错误:关闭失败,该文件已经是关闭状态!n”); return;} user->open=0;printf(“文件已经成功关闭!”);} /*没有文件夹关闭原因: 文件夹一打开就会跳向打开的新文件里 而文件夹关闭就会直接返回上一级的目录,若想整个文件夹都关闭,直接退出就可以了 因此不会直接关闭某个特定的文件*/ FFile backf(FFile user)/*返回上一层目录*/ { if(user->parent==NULL){ printf(“错误:返回失败,此处是最顶层目录!n”); return(user);} } user->open=0;user=user->parent;return(user);void readfile(FFile user)/*读文件*/ { char ch[20];int a; printf(“选择要读取的文件名:n”);scanf(“%s”,ch);if(user->child==NULL){ printf(“错误:读取失败,该目录下没有可读取的文件!n”);return;} user=user->child;for(a=1;;a++)//找出要读取文件的所在位置 { if(!strcmp(user->name,ch)) break;if(user->brother==NULL){ printf(“错误:读取失败,当前位置没有该文件!n”); return;} user=user->brother;} if(user->open==0){ printf(“错误:文件读取失败,该文件处于关闭状态!n”);return;} else if(user->iffile.read==0){ printf(“错误:文件读取失败,该文件受保护,禁止读取!n”);return;} printf(“读操作,该文件中的内容:n”);if(!strcmp(user->iffile.ch,“NULL”)){ printf(“该文件内没有可读内容!n”);return; } } printf(“%sn”,user->iffile.ch);printf(“文件读取成功!n”);void writefile(FFile user)/*写文件*/ { char ch[20];int a; } printf(“选择要进行写操作的文件名:n”);scanf(“%s”,ch);if(user->child==NULL){ printf(“错误:写操作失败,该目录下没有可写的文件!n”);return;} user=user->child;for(a=1;;a++)//找出要读取文件的所在位置 { if(!strcmp(user->name,ch)) break;if(user->brother==NULL){ printf(“错误:写操作失败,当前位置没有该文件!n”); return;} user=user->brother;} if(user->open==0){ printf(“错误:文件写操作失败,该文件处于关闭状态!n”);return;} else if(user->iffile.write==0){ printf(“错误:文件写操作失败,该文件受保护,禁止写!n”);return;} printf(“写操作,输入内容:n”);scanf(“%s”,user->iffile.ch);user->iffile.length=strlen(user->iffile.ch);printf(“文件进行写操作成功!n”); FFile copyfile(FFile user,FFile copyf)/*拷贝文件*/ { char ch[20];int a;printf(“选择要进行拷贝的文件(夹)名:n”);scanf(“%s”,ch); if(user->child==NULL){ printf(“错误:拷贝失败,该目录下没有可拷贝的文件!n”); return(NULL);} user=user->child;for(a=1;;a++)//找出要拷贝文件的所在位置,用user替代 { if(!strcmp(user->name,ch)) break; if(user->brother==NULL) { printf(“错误:拷贝失败,当前位置没有该文件!n”); return(NULL); } user=user->brother;} copyf=user; } printf(“拷贝成功!n”);return(copyf);FFile fenpei(FFile copyf,FFile user,FFile parent)/*粘贴时,给已拷贝项分配内存空间,以及给对应信息赋值*/ { user=(Ffile*)malloc(sizeof(Ffile)); //parent对child的连接,以及brother之间的连接已经完成if(copyf->brother==NULL && copyf->child==NULL){ user->parent=parent; user->child=NULL; user->brother=NULL;} else{ if(copyf->brother!=NULL){ user->brother=fenpei(copyf->brother,user->brother,parent);//brother连接,兄弟节点有同一个父结点 user->brother->parent=user->parent;} else { user->brother=NULL;} if(copyf->child!=NULL){ //parent=p;user->child=fenpei(copyf->child,user->child,user); user->child->parent=user;//完成child对parent的连接 //child连接,自己孩子的父结点就是自己 } else { user->child=NULL; user->child->parent=user;} } //设置结点对应的信息 strcpy(user->name,copyf->name);user->open=copyf->open;user->type=copyf->type;if(user->type==2){ user->iffile.length=copyf->iffile.length; user->iffile.read=copyf->iffile.read; //user->iffile.type=copyf->iffile.type; user->iffile.write=copyf->iffile.write; strcpy(user->iffile.ch,copyf->iffile.ch);} return(user);} void prastefile(FFile user,FFile copyf)/*粘贴文件*/ //user是要粘贴的地方,copyf是要粘贴的内容,//有相同文件名的会判断会不会覆盖,或者是重命名 //在原树中进行新建操作 { int i,j;char ch[20];FFile p,user0,parent;parent=user;//记录父结点 user=user->child; p=user;//记录当前结点的前一个brother结点 strcpy(ch,“NULL”);if(copyf==NULL)//判断有没有拷贝文件 { printf(“错误:粘贴失败,还没有拷贝任何文件(夹)!n”); return;} //p=(Ffile*)malloc(sizeof(Ffile));//p->child=(Ffile*)malloc(sizeof(Ffile));//先给粘贴项分配内存空间 //p->child=fenpei(copyf,p->child,p); if(user==NULL)//当前位置没有任何文件结点 { } user=fenpei(copyf,user,parent);//是他自己要分配,不是孩子结点!!parent->child=user;user->brother=NULL;user->parent=parent;return;//该位置没有任何文件 for(j=1;;j++){ if(user->type==0)//开端的空结点,用新结点覆盖,即:当前位置没有文件结点 { user=user->parent; deletechildtree(p); user=fenpei(copyf,user->child,user);//返还增加的结点 user->brother=NULL; user->parent=parent; parent->child=user; } return;if(!strcmp(user->name,copyf->name)){ printf(“提示:该文件名已经存在!n”); printf(“请重命名文件:n”); printf(“输入新文件名:n”); scanf(“%s”,ch); } if(user->brother==NULL)//普通的退出条件 { break;} p=user;user=user->brother;} user->brother=fenpei(copyf,user->brother,user->parent);user->brother->parent=user->parent;//若要更名,粘贴分配完内存空间返回时再改变 if(strcmp(ch,“NULL”)) strcpy(user->brother->name,ch);printf(“粘贴成功。n”);} void showroute(FFile user)/*显示当前路径*/ { if(user->parent!=NULL){ showroute(user->parent);} printf(“%s/”,user->name);//路径中每个结点的输出项 } void change(FFile user){ char ch[20];int a,b; if(user->child==NULL) { } printf(“错误:属性修改失败,该目录下没有可修改的文件!n”);return;printf(“选择要进行属性修改的文件(夹)名:n”);scanf(“%s”,ch);user=user->child;for(a=1;;a++)//找出要拷贝文件的所在位置,用user替代 { if(!strcmp(user->name,ch)) break;if(user->brother==NULL){ printf(“错误:属性修改失败,当前位置没有该文件!n”); return;} user=user->brother;} if(user->type==1){ printf(“错误:文件夹不能进行属性修改!n”);return;} for(;;){ printf(“1.修改读权限;n”);printf(“2.修改写权限;n”);printf(“3.返回;n”);printf(“选择操作:n”);scanf(“%d”,&a);if(a==1){ printf(“0.禁止; 1.允许;n”);printf(“请选择:n”);scanf(“%d”,&b);user->iffile.read=b;printf(“修改成功!n”);} else if(a==2){ printf(“0.禁止; 1.允许;n”);printf(“请选择:n”);scanf(“%d”,&b);user->iffile.write=b; } } printf(“修改成功!n”);} else if(a==3){ return;} else { } printf(“错误:没有该操作!n”);void main()/*主函数*/ { FFile d,e,f;//f记录当前显示界面父结点位置 int a,b,c;char ch[20];a=0;printf(“******************************目录******************************n”);printf(“ 1.选择用户n”);printf(“ 2.退出n”); printf(“****************************************************************n”);for(;;){ printf(“选择操作:n”);scanf(“%d”,&a);if(a==1){ printf(“选择用户:n”);printf(“1.user1;n2.user2;n”);scanf(“%d”,&b);break;} else if(a==2){ printf(“欢迎使用。n”);exit(0);//系统退出的操作码 } else { printf(“错误:没有该操作!n”); } } //初始化打开列表 //initopen();//初始化各个用户的信息 //copyf=(Ffile*)malloc(sizeof(Ffile));//copyf=NULL;copyf=NULL;user1=init();strcpy(user1->name,“user1”);user2=init();strcpy(user2->name,“user2”);d=init();e=init();user1->child=d;user2->child=e;d->parent=user1;e->parent=user2;printf(“%d”,user1->child->type);if(b==1){ printf(“已经进入user1系统n”);f=user1;show(user1);}else{ } printf(“已经进入user2系统n”);f=user2;show(user2); for(;;){ printf(“****************************************************************n”);printf(“1.创建文件(夹) 5.读文件 9.显示当前路径 n”);printf(“2.删除文件(夹) 6.写文件 10.返回上一层目录 n”);printf(“3.打开文件(夹) 7.拷贝文件 11.改变普通文件属性n”);printf(“4.关闭普通文件 8.粘贴文件 12.退出n”);printf(“****************************************************************n”);printf(“选择操作:n”);scanf(“%d”,&c);if(c==12){ break;}else if(c==1){ creatf(f);} else if(c==2){ printf(“选择要删除的文件(夹)的名字:n”);scanf(“%s”,ch);deletefile(f,ch);} else if(c==3){ f=openff(f);} else if(c==4){ closefile(f);} else if(c==5){ readfile(f);} else if(c==6){ writefile(f);} else if(c==7){ copyf=copyfile(f,copyf);} else if(c==8){ prastefile(f,copyf);copyf=NULL;} else if(c==9){ printf(“路径为:n”);showroute(f);printf(“n”);} else if(c==10){ } f=backf(f); } else if(c==11){ change(f);} else { continue;} show(f);} printf(“欢迎使用!n”); 操作系统课程设计 设计题目 动态分区分配存储管理 学生姓名学 号 专业班级 指导教师 吕 霆 20102675 计算机10-01班 第一章 课程设计概述 1.1 设计任务: 动态分区分配存储管理 1.2 设计要求 建立描述内存分配状况的数据结构; 建立描述进程的数据结构; 使用两种方式产生进程:(a)自动产生,(b)手工输入; 在屏幕上显示内存的分配状况、每个进程的执行情况; 建立分区的分配与回收算法,支持紧凑算法; 时间的流逝可用下面几种方法模拟:(a)按键盘,每按一次可认为过一个时间单位;(b)响应WM_TIMER; 将一批进程的执行情况存入磁盘文件,以后可以读出并重放; 支持算法:首次适应算法、循环首次适应算法、最佳适应算法:最坏适应算法。 1.3 设计目的 旨在让我们更好的了解动态分区管理方面的知识.第二章 原理及算法描述 2.1动态分区分配算法原理 首次适应算法 * 算法概述:分配内存时,从链首开始顺序查找,找到满足的空闲分区则划出空间分配,余下的空闲空间仍保留在空闲链表中 * 实现方法:分配时从数组第一个元素开始比较,若符合条件则将该元素减去对应作业的值 循环首次适应算法 * 算法概述:由首次适应算法演变,只是每次分配改为由上一次找到的空闲分区开始查找 * 实现方法:在首次适应算法的基础上增加一个值用于记录找到的空闲分区的位置 最佳适应算法 * 算法概述:每次为作业分配内存时,总是把能满足要求、又是最小的空闲分区 分配给作业 * 实现方法:我们决定每次分配先把空闲分区按从小到大的顺序排列,然后将第一个匹配分区分配给作业 最坏适应算法 * 算法概述:每次为作业分配内存时,总是挑选一个最大的空闲分区分割给作业使用 * 实现方法:算法与最佳适应算法几乎相同,仅在排序时把空闲分区表按从大到小的顺序排列,所以未作详细注释 回收分区 当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区链(表)中找到相应的插入点,此时可能出现以下四种情况之一;1)回收区与插入点的前一个空闲分区F1相邻接,此时应将回收区与插入点的前一分区合并,不必为回收区分配新表项,而只需修改其前一分区F1的大小.2)回收分区与插入点的后一空闲分区F2相邻接,此时也可将两分区合并,形成新的空闲分区,但用回收区的首址作为新空闲区的首址,大小为两者之和.3)回收区同时与插入点的前,后两个分区邻接,此时将三个分区合并,使用F1的表项和F1的首址,取消F2的表项,大小为三者之和.4)回收区既不与F1相邻接,又不与F2邻接.这时应为回收区单独建立一新表项,填写回收区的首址和大小,并根据其首址插入到空闲链中的适当位置.紧凑算法 通过移动内存中的作业的位置,以把原来多个分散的小分区拼接成一个大分区的方法.第三章 开发环境 此程序是本人利用c++语言在vs2012的开发环境中实现的第四章 程序实现--数据结构 #include int recycle;//需要回收的盘块序号 int id1;//算法选择号 int m;//内存区数 int n;//空闲区数 int q;//进程数 int r=0;//循环首次适应算法:对应的这次查找到的空闲分区序号 //打印输出函数 void vision(){ int i;int j;if(id1==1)stream.open(“first_fit.txt”, ios::app);if(id1==2)stream.open(“nextfirst_fit.txt”, ios::app);if(id1==3)stream.open(“best_fit.txt”,ios::app);if(id1==4)stream.open(“worst_fit.txt”, ios::app);if(id1==5)stream.open(“compact.txt”,ios::app);if(id1==6)stream.open(“huishou.txt”,ios::app);cout<<“-------------内存分配状态-------------”< } cout < } cout < } //作业信息的自动产生 void create_pro(){ } //作业的手动生成 void create_zuoye(){ int j;int choice2;int id3=rand()%10;m=id3;//内存区数量 cout<<“产生”< } ary3[0]=42;ary3[1]=86;ary3[i]=rand()%100;if(ary3[i]==0){i--;} { } cout<<“--------------------------”< } //内存信息的自动产生 void create_apply(){ int k=0;//空闲区数量 for(i=0;i if(ary1[i][3]!=2){ary2[k][0]=ary1[i][0];ary2[k][1]=ary1[i][1];ary2[k][2]=ary1[i][2];k++;} int i;for(i=0;i } ary1[i][0]=i+1;ary1[i][1]=rand()%100;if(i==0){ } ary1[i][3]=rand()%3;//cout <>choice2;q=choice2;cout<<“输入想创建的作业请求大小”< } cout<<“你创建了”< } //内存信息的手动生成 int create_fenqu(){ } //首次适应算法 void first_fit()int k,x,y,o=0;int a=0;cout<<“输入想创建的内存分区块数 : ”;cin>>k; cout<<“输入”< } cout<<“输入内存块的分配状态”< } ary1[0][2]=0;ary1[1][2]=ary1[0][1];for(int i=2;i for(int i=0;i } n=a;return m,n;if(ary1[i][3]!=2){ } ary2[a][0]=ary1[i][0];ary2[a][1]=ary1[i][1];ary2[a][2]=ary1[i][2];a++;ary1[i][2]=ary1[i-1][2]+ary1[i-1][1];//起始地址 cin>>y;if(y==2){ } ary1[i][3]=y;//状态 n++;ary1[i][0]=i;//序号 cin>>x;ary1[i][1]=x;//大小 } n=k;//空闲块数量 { vision();int i;int j;int k;int l;int d;//用来保存第k个的值 int id2=0;for(i=0;i for(j=0;j if(ary2[j][1]>=ary3[i])//进程占用空间小于等于其中一个空闲区的大小 { cout<<“[”< ary1[ary2[j][0]-1][3]=2;for(k=j+1;k ary2[k-1][0]=ary2[k][0];ary2[k-1][1]=ary2[k][1];ary2[k-1][2]=ary2[k][2];} n--; }else//否则的话,空闲链对应的地方盘块大小小了进程占用的大小,并且内存分配从对应的 { l=ary2[j][0];d=ary1[l-1][1];//大小 ary1[l-1][1]=ary3[i];ary1[l-1][3]=2;m++;for(k=m;k>ary2[j][0]+1;k--){ ary1[k-1][0]=ary1[k-2][0]+1;ary1[k-1][1]=ary1[k-2][1];ary1[k-1][2]=ary1[k-2][2];ary1[k-1][3]=ary1[k-2][3];那一项开始增加一项 } l=ary2[j][0]; } } { if(ary1[id2][3]!=2) } } n=k;} break;} else { } cout<<“[”< { ary2[k][0]=ary1[id2][0];ary2[k][1]=ary1[id2][1];ary2[k][2]=ary1[id2][2];k++;} ary1[l][0]=l+1;ary1[l][1]=d-ary3[i];ary1[l][2]=ary1[l-1][1]+ary1[l-1][2];ary1[l][3]=0;k=0;for(id2=0;id2 //首次循环适应算法 void next_fit(){ vision();int i;int j;int k;int s;int d;int id2;for(i=0;i { for(j=r;j if(ary3[i]<=ary2[j][1]){ cout<<“[”< { } else//对应的空闲块大小大于进程需要大小 { //-----改变内存分配情况-----r=(r+1)%n;//改变第k块的内容 k=ary2[j][0];d=ary1[k-1][1];ary1[k-1][1]=ary3[i];ary1[k-1][3]=2;//从k+1之后所有向后移一格 m++;//内存块数增加1 for(s=m-1;s>k;s--){ ary1[s][0]=ary1[s-1][0]+1;ary1[s][1]=ary1[s-1][1];ary1[s][2]=ary1[s-1][2];//---改变内存分配---k=ary2[j][0];//得到对应空闲块对应内存块的序号 k--;ary1[k][3]=2;//把对应内存块标志位上改成已分配 //------------------//--改变空闲块表:把从这块空闲块以下的所有空闲块向上移一格--n--;for(k=j;k } vision();//------------------break;ary2[k][0]=ary2[k+1][0];ary2[k][1]=ary2[k+1][1];ary2[k][2]=ary2[k+1][2];stream<<“[”< } } //思路:先把空闲列表检索一遍,选出最佳答案,进行分配 void best_fit()//最佳算法--按顺序检索,把与进程要求内存大小最接近的快分配给进程 { int i;int s;int j=-9999;//用来保存最接近的答案 int e;//用来存放进行比较时的中间结果 } { if(ary1[id2][3]!=2) } } else{ } cout<<“[”< { ary2[k][0]=ary1[id2][0];ary2[k][1]=ary1[id2][1];ary2[k][2]=ary1[id2][2];k++;} ary1[s][3]=ary1[s-1][3];} //改变第k+1块内容:对应的数组是ary1[k] ary1[k][0]=ary1[k-1][0]+1;ary1[k][1]=d-ary1[k-1][1];ary1[k][2]=ary1[k-1][1]+ary1[k-1][2];//--------------------------//----改变空闲表分配情况----k=0;for(id2=0;id2 }else { cout<<“[”< for(s=0;s } if(j<0){ cout<<“[”< if(ary2[j][1]==ary3[i]){ } else for(l=k;l } n--;ary2[l-1][0]=ary2[l][0];ary2[l-1][1]=ary2[l][1];ary2[l-1][2]=ary2[l][2];ary1[k-1][3]=2;k=ary2[j][0]; } //最坏适应算法 void worst_fit() } { if(ary1[id2][3]!=2) } } vision();n=k; } for(k=j+1;k { ary2[k][0]=ary1[id2][0];ary2[k][1]=ary1[id2][1];ary2[k][2]=ary1[id2][2];k++;} { //把对应的内存分配进行更改 k=ary2[j][0];d=ary1[k-1][1];ary1[k-1][1]=ary3[i];ary1[k-1][3]=2;m++;for(l=m;l>ary2[j][0]+1;l--){ } k=ary2[j][0];ary1[k][0]=k+1;ary1[k][1]=d-ary1[k-1][1];ary1[k][2]=ary1[k-1][1]+ary1[k-1][2];ary1[k][3]=0;k=0;ary1[l-1][0]=ary1[l-2][0]+1;ary1[l-1][1]=ary1[l-2][1];ary1[l-1][2]=ary1[l-2][2];ary1[l-1][3]=ary1[l-2][3];for(id2=0;id2 { }else { cout<<“[”< int e=-9999;//用来存放进行比较时的中间结果 int k;int l;int d;int id2;vision();{ j=-9999;e=-9999;for(s=0;s } if(j<0){ cout<<“[”< if(ary2[j][1]==ary3[i]){ k=ary2[j][0]; ary1[k-1][3]=2; for(l=k;l { if(ary1[id2][3]!=2) } } vision();n=k; } for(k=j+1;k { ary2[k][0]=ary1[id2][0];ary2[k][1]=ary1[id2][1];ary2[k][2]=ary1[id2][2];k++;} } else { //把对应的内存分配进行更改 k=ary2[j][0];d=ary1[k-1][1];ary1[k-1][1]=ary3[i];ary1[k-1][3]=2;m++;for(l=m;l>ary2[j][0]+1;l--){ } k=ary2[j][0];ary1[k][0]=k+1;ary1[k][1]=d-ary1[k-1][1];ary1[k][2]=ary1[k-1][1]+ary1[k-1][2];ary1[k][3]=0;k=0;ary1[l-1][0]=ary1[l-2][0]+1;ary1[l-1][1]=ary1[l-2][1];ary1[l-1][2]=ary1[l-2][2];ary1[l-1][3]=ary1[l-2][3];} n--;ary2[l-1][2]=ary2[l][2];for(id2=0;id2 } //回收内存算法: /* 有共计八种情况,1.(1)回收区上邻接着空闲盘块,下连接着已分配盘块(2)回收区下邻接着空闲盘块,上邻接着已分配盘块(3)回收区上下连接的都是空闲盘块(4)空闲区上下邻接的都是已分配盘块 (5)要回收的盘块就是第一个盘块,并且向下邻接着空闲盘块(6)要回收的盘块就是第一个盘块,但是向下邻接着已分配盘块(7)要回收的盘块就是最后一个盘块,并且向上邻接的是空闲盘块(8)要回收的盘块就是最后一个盘块,但是向上邻接的是已分配盘块 */ void apply_recycle(){ ary1[0][1]=ary1[0][1]+ary1[1][1];ary1[0][3]=0;for(i=1;i if(recycle==1){ //cout< if(ary1[1][3]!=2){ cout<<“要回收的盘块就是第一个盘块,并且向下邻接着空闲盘块”< } else { ary1[0][3]=0;n++;ary2[0][0]=1;ary2[0][1]=ary1[0][1];ary2[0][2]=ary1[0][2];vision();} stream<<“要回收的盘块就是第一个盘块,并且向下邻接着空闲盘块”< ary2[k][0]=ary1[j][0]; ary1[0][3]=0;k=0;for(j=0;j //cout<<“ary1[j][3]”< } else{ cout<<“要回收的盘块就是第一个盘块,但是向下邻接着已分配盘块”< } n=k;vision(); } ary2[k][0]=ary1[j][0];ary2[k][1]=ary1[j][1];ary2[k][2]=ary1[j][2];k++; { } m--;// cout<<“" k=0;vision();//cout<<”ary1[0][3]“< cout<<”ary1[j][3]“< } else{ cout<<”要回收的盘块就是最后一个盘块,但是向上邻接的是已分配盘块“< } n=k;vision(); } ary2[k][0]=ary1[j][0];ary2[k][1]=ary1[j][1];ary2[k][2]=ary1[j][2];k++; ary1[recycle-2][3]=0;ary1[recycle-2][1]=ary1[recycle-2][1]+ary1[recycle-1][1];m--;k=0;for(j=0;j //cout<<”ary1[j][3]“< } else if(recycle==m){ if(ary1[recycle-2][3]!=2){ cout<<”要回收的盘块就是最后一个盘块,并且向上邻接的是空闲盘块“< } n=k;vision(); } ary2[k][1]=ary1[j][1];ary2[k][2]=ary1[j][2];k++;stream<<”要回收的盘块就是最后一个盘块,并且向上邻接的是空闲盘块“< ary2[k][0]=ary1[j][0];ary2[k][1]=ary1[j][1];ary2[k][2]=ary1[j][2];k++; } else{//剩下比较复杂的四种情况 if((ary1[recycle-2][3]!=2)&&(ary1[recycle][3]==2))//回收区上邻接着空闲盘块,下连接着{cout<<”回收区上邻接着空闲盘块,下连接着已分配盘块“< } } n=k;vision(); } ary2[k][0]=ary1[j][0];ary2[k][1]=ary1[j][1];ary2[k][2]=ary1[j][2];k++; ary1[recycle-1][3]=0;k=0;for(j=0;j //cout<<”ary1[j][3]“< stream<<”回收区上邻接着空闲盘块,下连接着已分配盘块“< ary1[recycle-2][1]=ary1[recycle-2][1]+ary1[recycle-1][1];for(i=recycle-1;i } m--;k=0;for(j=0;j //cout<<”ary1[j][3]“< } if((ary1[recycle-2][3]!=2)&&(ary1[recycle][3]!=2))//回收区上下连接的都是空闲盘块 { cout<<”回收区上下连接的都是空闲盘块“< } vision(); } ary2[k][0]=ary1[j][0];ary2[k][1]=ary1[j][1];ary2[k][2]=ary1[j][2];k++; } n=k;vision();} if((ary1[recycle][3]!=2)&&(ary1[recycle-2][3]==2))//回收区下邻接着空闲盘块,上邻接着{ cout<<”回收区下邻接着空闲盘块,上邻接着已分配盘块“< stream<<”回收区下邻接着空闲盘块,上邻接着已分配盘块“< ary1[recycle-2][3]=0;ary1[recycle-2][1]=ary1[recycle-2][1]+ary1[recycle-1][1];for(i=recycle-1;i } m--;k=0;for(j=0;j //cout<<”ary1[j][3]“< } } } if((ary1[recycle-2][3]==2)&&(ary1[recycle][3]==2))//空闲区上下邻接的都是已分配盘块 { } ary1[recycle-1][3]=0;k=0;for(j=0;j } vision();//cout<<”ary1[j][3]“< } ary2[k][0]=ary1[j][0];ary2[k][1]=ary1[j][1];ary2[k][2]=ary1[j][2];k++;cout<<”回收区上下连接的都是空闲盘块“< } m=m-2;k=0;for(j=0;j } vision();//cout<<”ary1[j][3]“< } ary2[k][0]=ary1[j][0];ary2[k][1]=ary1[j][1];ary2[k][2]=ary1[j][2];k++;ary1[recycle-1][0]=ary1[recycle+1][0]-2;ary1[recycle-1][1]=ary1[recycle+1][1];ary1[recycle-1][2]=ary1[recycle+1][2];ary1[recycle-1][3]=ary1[recycle+1][3];n=k;n=k; } //紧凑算法 void compact(){ num_avl=0;for(id2=0;id2 int num_avl;//记录空闲盘块数量 int sum_avl=0;//总共空闲区大小 int num_apl=0;//统计总共空闲区有多大 vision();for(id2=0;id2 } //最后一块空闲块 ary1[num_apl][0]=num_apl+1;ary1[num_apl][1]=sum_avl;ary1[num_apl][2]=ary1[num_apl-1][1]+ary1[num_apl-1][2];ary1[num_apl][3]=0;m=num_apl+1;//包括最后一个空闲区 if(ary1[id2][3]==2){ } ary1[num_apl][0]=num_apl+1;ary1[num_apl][1]=ary1[id2][1];if(num_apl==0){ } ary1[num_apl][3]=2;num_apl++;//cout<<”num_apl“< } //主函数入口 void main(){ if(choice1==1){ } num=rand()&10;q=num;int id3=2+rand()%8;m=id3;//内存区数量 create_apply();create_pro();int i;int j;int num;int choice1;//操作选择标记 int choice2;int flag=1;//标记是否再执行 while(flag==1){ cout<<”********************************************“< } n=num_avl;vision(); } ary2[num_avl][0]=ary1[id2][0];ary2[num_avl][1]=ary1[id2][1];ary2[num_avl][2]=ary1[id2][2];num_avl++;if(choice1==2){ } vision(); cout<<”**------------------请选择处理算法----------------------**“< } } cout<<”**************************** “< cout<<”**1首次适应算法-----2循环首次适应算法-----3最佳适应算法 **“< } {first_fit();} {next_fit();} {best_fit();} {worst_fit();} { compact();} if(id1==6){ cout<<”*******************生成内存状态******************“< } cout<<”错误:内存中不存在此块!“< } if(id2==-9999){ apply_recycle();} if(ary2[i][0]==recycle){ } cout<<”错误:输入的为空闲盘块!"< 中南林业科技大学 操作系统课程设计 课程题目:模拟磁盘文件管理的程序 姓名: 学号: 专业: 计算机科学与技术 年级: 2006 计算机科学学院 2008年11月 模拟磁盘文件管理的程序 一、课程设计内容 ⑴ 自定义磁盘文件管理的数据结构; ⑵ 能够自由创建、修改、删除文件; ⑶ 文件具有一定自定义的属性; ⑷ 能够显示当前系统文件的状态。 二、课程设计的数据结构说明 程序中定义了两个类: class file//文件类 {private: char name[10];//文件名 public: int tag;//删除标记 1:已删 0:未删 file(){ } char *getname(){return name;} //获取文件名 int gettag(){return tag;} //获取删除标记 int getlength(){return length;} //获取文件大小 int getblocknum(){return blocknum;} // 磁盘块数 int getblocksum1(){return blocksum1;} //磁盘块号的始点 int getblocksum2(){return blocksum2;} //磁盘块号的终点 int length,blocknum,blocksum1,blocksum2; void setname(char na[ ]){strcpy(name,na);} //设置文件名 void delwenjian(){ tag=1;}//设置删除标记 1:已删 0:未删 void creatfile(char *na,int L,int num,int s1,int s2)//创建文件 void deltefile(char *na){tag=1;strcpy(name,na);} //删除文件 void disp()//输出文件信息 class fdatabase //文件库类 { private: int top;//文件记录指针 file f[50];public: fdatabase(){top=-1;} //构造函数 int search(char *fname)//按文件名查找 int creatfile(char *na,int L,int num,int s1,int s2)//创建文件时先查找是否存在 int deltefile(char *na)//删除文件时先查找是否存在 void disp()//输出所有文件信息 }; 三、课程设计的模板说明 1、初始化,建立文件系统 输入磁盘大小(G),每个盘块大小(M),自动建立位示图,位示图字长定为32位 输出位示图的行数,以及行号、列号与磁盘块号的转换公式(都从0开始编号)。 2、循环选择执行以下功能 1、存储文件 输入建立的文件名和文件大小,如果该文件名已经存在,则输出不能建立的信息否则计算所需的磁盘块数 为其分配足够多的磁盘块,并记录下来 输出所占用的磁盘块号 2、删除文件 输入要删除的文件名,如果该文件名不存在,则输出删除错误信息,否则收回该文件所占用的磁盘块 删除该文件名 3、显示位示图情况 显示位示图的情况 显示剩余磁盘块的数目 4、显示文件列表 显示文件名,文件大小,占用的磁盘块数目和磁盘块号 四、课程设计的源代码 #include char name[10];//文件名 public: int tag;//删除标记 1:已删 0:未删 file(){ } char *getname(){return name;} //获取姓名 int gettag(){return tag;} //获取删除标记 int getno(){return no;} //获取文件编号 int getlength(){return length;} //获取文件大小 int getblocknum(){return blocknum;} // 磁盘块数 int getblocksum1()//磁盘块号的始点 { return blocksum1;} int getblocksum2()//磁盘块号的终点 { return blocksum2;} int length;//文件大小 int blocknum;//盘块数 int blocksum1;//所占盘块号的始点 int blocksum2;//所占盘块号的终点 void setname(char na[ ])//设置文件名 {strcpy(name,na);} void delwenjian(){ tag=1;}//设置删除标记 1:已删 0:未删 void creatfile(char *na,int L,int num,int s1,int s2)//创建文件 { tag=0;length=L;blocknum=num;blocksum1=s1;blocksum2=s2;strcpy(name,na);blocknum=length/m;//盘块数=文件大小/盘块大小 if(length%m!=0)//盘块数取上整 blocknum=blocknum+1;cout<<“ 所需磁盘块数:”< for(;j<32;j++) a[i][j]=1;i=i+1;for(j=0;j<(sum+blocknum)-32;j++)//再进行剩余项赋值 { a[i][j]=1;} sum=sum+blocknum-32;} tt=tt+blocknum;//输出文件所占用的盘块号 cout<<“ 所占磁盘块号:”< { for(ii=0;ii<=top;ii++) { if(strcmp(f[ii].getname(),fname)==0 && f[ii].tag==0) return 0; } return 1;} int creatfile(char *na,int L,int num,int s1,int s2)//创建文件时先查找是否存在 { int p;p=search(na); if(p==1) { top++; f[top].creatfile(na,L,num,s1,s2); return 1;} else {cout<<“!!该文件已存在,不能创建!!nn”; return 0;} } int deltefile(char *na)//删除文件时先查找是否存在{int b,p,x=0,n1,n2,q1,q2,t;p=search(na);if(p==0)//若文件存在 { //进行删除文件赋值 f[ii].tag=1;b=f[ii].length/m;//盘块数=当前文件大小/盘块大小 if(ii==0)// 对第一个删除文件进行赋值 for(k=0;k a[x][k]=0; else{ n1=(f[ii-1].blocksum2+1)/32;//被查找的文件之前文件所占用的盘块数 /32,//大于0表示跨行 n2=(f[ii].blocksum2+1)/32;//所有文件所占用的盘块数/32,大于0表示跨行 q1=(f[ii-1].blocksum2+1)-n1*32;// 当前文件的开始盘块号 q2=(f[ii].blocksum2+1)-n2*32;// 用于跨行后计算盘块号 t=n2-n1;if(t==0)//若n2与n1相等,表明当前所有被占用盘块在同一行 for(k=q1;k<1+b;k++) a[n2][k]=0; else { if((f[ii-1].blocksum2+1)%32==0)//前面所占用的盘块数是32倍数 { x=x+n1;//当前文件赋值 for(;t-1>=0;t--,x++)//循环进行整行赋值 for(k=0;k<32;k++) a[x][k]=0; x=n2;//对剩余项赋值 for(k=0;k a[x][k]=0; } else //对当前文件前几项赋值 { x=n1; for(k=q1;k<32;k++) a[x][k]=0;x=x+1;int t1=t; for(;t-1>0;t--,x++)//中间整行赋值 for(k=0;k<32;k++) a[x][k]=0; x=n2;//最后剩余项赋值 for(k=0;k<(f[ii].blocksum2+1)-t1*32;k++) a[x][k]=0; } } return 1;} } else {cout<<“该文件不存在”; return 0;} } void disp()//输出所有文件信息 { for(int i=0;i<=top;i++) if(f[i].tag==0)第二篇:操作系统课程设计文件管理
第三篇:操作系统课程设计_动态分区分配存储管理
第四篇:操作系统课程设计++模拟磁盘文件管理的程序