操作系统实习报告
题 目 基于shell的形式来模拟文件系统
班 级
学 号
姓 名
11 学年— 12 学年第 2学期 操作系统实习报告书
专 业: 班 级:
姓 名:
学 号:
实习地点: 辅导教师:
实习内容: 基于shell的形式来模拟文件系统
实习环境: Windows操作系统相应的开发平台和工具
实习步骤、方法、技术方案、结果、分析:
实习内容:
在一个文件中模拟文件系统如何存储文件和目录。
通过一个Shell来模拟对该文件系统中文件和目录的访问和操作。
在模拟中提供文件系统空间整理的功能。
实习要求:
文件系统的基本要求:
1、使用大小固定的文件来代表一个文件系统分区,例如,30K字节。文件大小的固定是由程序里面自己控制的,即在给定文件大小后面不再写内容。
2、每个分区都要支持多级目录的文件组织形式,并且文件的大小可动态变化。其中,存放的文件都为简单的TXT文本,即字符型文件。
运行程序的基本要求:
编写一个shell程序。该程序能像cmd.exe一样,能对你所构造的文件系统进行目录和文件操作。
要求实现地功能包括:cd、dir、mkdir,more,copy,rmdir,find,attrib,copy,del,xcopy,exit等几个ms-dos命令。
实习步骤:
1. 首先理解该课程设计的要求,弄清楚shell的各种操作,查找各种资料,明白一个多级目录的文件系统是什么样的,加深理解文件系统的组成以及各种内部结构。
2. 通过查找各种资料来搞清楚文件系统的存储形式,写出相关的结构体定义以及大体框架结构。
3. 编写各个功能的代码函数来实现shell程序中目录与文件的操作。在基本的功能都实现以后对写出的程序进行一些必要的调试和修改,在此过程中找出问题并改正。
4. 运用学过的多线程的方法将该程序改为多线程实现的shell程序。
5. 总结经验,书写相关的实习报告书
实习方法:
1. 理解文件系统存储结构,查找多级存储结构文件系统的相关资料,常见的UNIX实现了层次结构化文件的系统。在该方案中,目录中可以包含多个文件和子目录。磁盘被分成多个区。每个分区有自己的文件系统。如下图所示,矩形代表目录,圆圈代表文件,在UNIX操作系统中,目录也被当作文件。它认为目录是单个文件或多个文件。
2. UNIX文件系统的中心概念是超级块superblock, i节点inode,数据块data block,目录块directory block,和间接块indirection block。超级块占用第1号物理块,是文件系统的控制块,超级块包括:文件系统的大小、空闲块数目、空闲块索引表、空闲i节点数目、空闲i节点索引表、封锁标记等。超级块是系统为文件分配存储空间、回收存储空间的依据。i节点包括除了名字外的一个文件的所有信息,名字与i节点数目一起存在 目录中。结合上图,可以对下图进行理解:
3. 磁盘的大小是固定的并且存储是连续的,所以用一个固定大小的文本文件来代表一个磁盘分区,并通过对此文本的内容读写来模拟shell程序中该文件系统中文件和目录的访问和操作。若不存在该文本,则必须对其初始化,形成一个根目录。初始化的操作有:
初始化超级块(代表一个根目录)Init_SuperBlock();
初始化i结点 Init_INode();
初始化数据块 Init_DataBlock();
4. 模拟对磁盘的访问,通过对文件进行文件seekp定位操作来实现,固定文件的大小由起初写入的文本决定,二进制文件编码是变长的,它灵活,存储利用率高,所以以二进制读写的方式来对本文进行操作。
5. 用多线程的方法来实现shell程序,第一个用来接受命令,第二个用来解析命令,第三个用来实现命令。实现的关键点是在定义互斥量和信号量, 并在三个线程中来进行所需的P、V操作。
技术方案:
1. 定义相关的结构体:
//超级块
typedef struct
{
int MaxSize; //文件系统的大小
int FirstINodeBlk; //第一个I结点块号
int FirstDBlk; //第一个数据块号
int BlockSize; //每个物理块大小
bool INodeStatus[INODES]; //INode状态(空闲或占用)
bool DataBlockStatus[DATABLKS]; //数据块状态(空闲或占用)
}SuperBlock;
//i结点
typedef struct
{
int FileType; //文件类型
int INodeNumber; //i-node号
int LinksNum; //链接数
int FileSize; //文件大小
int blocks[4]; //占用的数据块
}INode;
//目录结构,结构体大小为16B
typedef struct DirectoryItem
{
int INodeNumber; //INode号
char FileName[12]; //文件名
}DirectoryItem;
2. 声明各种函数(所实现的相关功能):
//Command.h
void PrintCurPath(); //输出当前路径
void SplitCmd(char *Cmd,char *cmd,char *config);//对命令进行分割
void mkdir(char *config); //新建一个目录
void more(char *config); //逐屏显示输出
void dir(char *config); //显示目录中的文件和子目录
void help(char*config); //帮助
void cd(char*config); //显示或改变当前目录
void rm(char*config); //删除一个目录
void format(); //格式化磁盘
void InterpretCmd(); //对命令解析
//SuperBlock.h
void Init_SuperBlock(); //初始化超级块
void WriteSuperBlock(); //写超级块到文件中
void ReadSuperBlock(); //从文件中读取超级块
//INode.h
void Init_INode(); //初始化i结点
int AllocINode(); //申请I-结点
void WriteINode(int,INode); //写I-结点到文件中
void ReadINode(int,INode&); //从文件中读取I-结点
void FreeINode(int); //释放I-结点
void SetDirINode(INode&, int,int); //初始化新建的目录I-结点
void SetFleINode(INode&,int,int ,int*,int); //初始化新建的文件I-结点
void UpdataINode(int); //更新I-结点
//Directory.h
bool HaveSameName(char *,INode); //寻找是否有相同的文件名
bool FindDir(char *,INode, int, DirectoryItem&); //查找目录项
void SetDirItem(char *c,int,DirectoryItem&); //初始化新建的目录项
void WriteDir(INode,DirectoryItem,int); //写目录项
void ReadDir(int,INode,DirectoryItem &); //读目录项
//DataBlock.h
void Init_DataBlock(); //初始化数据块
int AllocDBlk(); //申请数据块
void WriteDBlk(int *,int,char *); //释放数据块
void FreeDBlk(int); //写数据块
3. 必要的初始化操作:
//初始化超级块
void Init_SuperBlock()
{
superblock.MaxSize=240*BLKSIZE;
superblock.BlockSize=BLKSIZE;
superblock.FirstINodeBlk=FIRSTIBLK;
superblock.FirstDBlk=FIRSTDBLK;
for(int i=0;i<INODES;i++)
{
superblock.INodeStatus[i]=true;
}
for(i=0;i<DATABLKS;i++)
{
superblock.DataBlockStatus[i]=true;
}
//0号I-结点的被根目录使用,0号数据块被根目录使用
superblock.INodeStatus[0]=false;
superblock.DataBlockStatus[0]=false;
fstream fout;
fout.open("A.txt",ios::out|ios::binary);
if(!fout)
{
cout<<"Can't open this file"<<endl;
exit(0);
}
fout.write((char*)&superblock,FIRSTIBLK*BLKSIZE);
fout.close();
}
//初始化I-结点
void Init_INode()
{
for(int i=0;i<INODES;i++)
{
inode[i].FileType=UNKNOW;
inode[i].INodeNumber=i;
inode[i].LinksNum=0;
inode[i].FileSize=0;
for(int j=0;j<4;j++)
{
inode[i].blocks[j]=-1;
}
}
//0号I-结点被根目录占用,0号数据块被根目录使用
inode[0].FileType=ISDIR;
inode[0].blocks[0]=0;
inode[0].LinksNum=2;
fstream fout;
fout.open("A.txt",ios::in|ios::out|ios::binary);
if(!fout)
{
cout<<"Can't open this file"<<endl;
exit(0);
}
fout.seekp(FIRSTIBLK*BLKSIZE);
for( i=0;i<INODES;i++)
{
fout.write((char*)&inode[i],sizeof(INode));
}
fout.close();
}
//初始化数据块
void Init_DataBlock()
{
fstream fout;
fout.open("A.txt",ios::in|ios::out|ios::binary);
if(!fout)
{
cout<<"Can't open this file"<<endl;
exit(0);
}
fout.seekp(FIRSTDBLK*BLKSIZE);
//初始化根目录
DirectoryItem RootDir[2];
strcpy(RootDir[0].FileName,".");
RootDir[0].INodeNumber=0;
strcpy(RootDir[1].FileName,"..");
RootDir[1].INodeNumber=0;
for(int i=0;i<2;i++)
{
fout.write((char*)&RootDir[i],sizeof(DirectoryItem));
}
fout<<setw(DATABLKS*BLKSIZE-1-sizeof(DirectoryItem)*2)<<'\0';
fout.close();
}
4. 定义多线程实现的互斥量和信号量初始化互斥量与信号量:
HANDLE mutex; //一个互斥量
HANDLE ghSemaphore1, ghSemaphore2, ghSemaphore3; //三个信号量
mutex = CreateMutex( NULL,FALSE,NULL); //初始化未被占用
ghSemaphore1 = CreateSemaphore( NULL, 1,1,NULL); //初始化最大资源值与可利用资源都为1
ghSemaphore2 = CreateSemaphore( NULL, 0,1,NULL); //初始化可利用资源为0,最大资源值为1
ghSemaphore3 = CreateSemaphore( NULL, 0,1,NULL); //初始化可利用资源为0,最大资源值为1
5. 整体流程图及重要功能函数的说明和流程图
1) 整体流程图:
2) 创建目录:
3) 删除操作del:
4) 改变当前目录:
5) 创建文件:
实习结果:
1. 进入运行界面:
2. 显示所能实现的功能
3. 使用mkdir创建目录:
4. 显示当前文件
5. 进入yuanyuan目录
6. 返回上一级:
7. 删除yuanyuan目录
8. 显示当前目录:
9. 创建一个文件并输入内容:
10. 显示当前文件的内容:
11. 格式化:
12. 退出程序:
实习分析:
通过本次的课程设计,使我能够正确运用操作系统课程中所学的基本理论和知识,加深了对文件系统基本概念的理解,以及磁盘文件系统的文件操作。设计一个软件,先要做好思路分析,这一点很重要,如果没有分析好思路,那么就会觉得思维混乱且无从下手,还有比较重要的是,需要先仔细画好流程图。在程序设计的开始,由于分析工作做得不够深入和细致,出了很多的错误。另外在运用C++的时候,感觉有点生疏,在编程和调试的过程中,经常会出现意想不到的问题,并非每个问题都可以从相关资料中找到解决方法,有些问题是由于自己的马虎所导致的,这就需要通过仔细的分析来解决问题。
在设计过程中,查询了不少相关资料,不断的发现问题、提出问题、解决问题。在对自己所编写的源程序段的纠错的过程中,使我更好的理解了操作系统中文件系统的理论知识,同时又把学到过的多线程加入到程序中来实现多线程方式的shell程序,让我对多线程的思想又有了更深一步的理解。总的来说通过这次课程设计使我学到了很多在平时的学习中学不到的很多东西,通过这次课程设计,使我对操作系统和编程产生了兴趣。我相信,只要不断的严格要求自己,注意培养自己的思维能力,就一定会有所收获和提高。
第二篇:操作系统实习报告
20##年秋—操作系统小学期
《操作系统小学期》
实习报告
成 绩:
评阅人:
学院:信息科学与技术学院
专业:计算机科学与技术
年级:2 0 0 8级
班级:信080 班
姓名:
学号:200
日期:20##年9月2日
一、问题描述:
1.分析进程的同步与互斥现象,编程实现经典的进程同步问题——生产者消费者问题的模拟;
2.编写允许进程并行执行的进程调度程序,在常用的进程(作业)调度算法:先来先服务算法、短作业优先算法、最高响应比优先算法、高优先权优先算法等调度算法中至少选择三种调度算法进行模拟,并输出平均周转时间和平均带权周转时间。
二、问题分析
1、进程管理是操作系统的职能之一,主要是对处理机进行管理 。为了提高CPU的利用率而采用多道程续技术。通过进程管理来协调多道程序之间的关系,使CPU得到充分的利用。
2、在问题的解决过程中,用到了三种算法:首先用到了先来先服务算法,通过insert函数判断各个进程的的到达时间,并将先到达的进程先运行;其次用到了最短作业优先算法,首先将第一个进程先运行,然后从第二个开始判断时间长短,将短作业先运行;最后用到了最高响应比优先算法,每次运行完一个进程之后将剩余进程重新比较优先级,将优先级高的进程先运行;然后用create函数求出周转时间的总和和带权周转时间的总和,并将二者除以总数N后输出。
三、数据模型描述
算法中需要的数据结构:
struct node; //定义的一个结构,其中包含五个时间变量和一个名称变量
用到的辅助函数:
void Print //帮助输出运行次序及平均周转时间和平均带权周转时间的函数
void insert //将到达时间早的进程排在作业队列的前面
void create //创建进程并输入作业名、到达时间、运行时间的函数求出周转时间和带权周转时间之和
四、算法描述
1解题算法的设计思路介绍
(1)先来先服务算法(FCFS):根据进程服务请求的顺序处理请求。
(2)短作业优先算法(SJF):对预计执行时间短的作业(进程)优先分派处理机。
(3)高响应比算法(TRRF):把CPU分配给就绪队列中响应比最高的进程。
2、程序结构、模块划分
3详细代码设计
#include<iostream>
using namespace std;
typedef struct node
{
char name[5];
int prio;
int cputime;
int needtime;
int needtime1;
int fnshtime;
char state;
struct node *next;
}PCB;
int choice;
PCB *finish,*ready,*tail,*run;
int m;
void firstin()
{
run=ready;
run->state='R';
ready=ready->next;
}
void print1()
{
PCB *p;
printf("\n name cputime needtime prio state\n");
if(run!=NULL)
printf(" %-10s%-10d%-10d%-10d %c\n",run->name,run->cputime,run->needtime,run->prio,run->state);
p=ready;
while(p!=NULL)
{ printf(" %-10s%-10d%-10d%-10d %c\n",p->name,p->cputime,p->needtime,p->prio,p->state);
p=p->next;
}
p=finish;
while(p!=NULL)
{ printf(" %-10s%-10d%-10d%-10d %c\n",p->name,p->cputime,p->needtime,p->prio,p->state);
p=p->next;
}
}
void print4()
{
int n=0;
float t=0;
PCB *p;
if(finish!=NULL)
p=finish;
if(choice==1||choice==2)
{
while(p!=NULL)
{
n+=p->fnshtime ;
t+=((float)(p->fnshtime)/p->needtime1);
printf("进程%s的完成时间为:%d\t周转时间为:%d\t带权周转时间为:%f\n",p->name,p->fnshtime,p->fnshtime,(float)p->fnshtime/p->needtime1);
p=p->next;
}
}
else
{
while(p!=NULL)
{
n+=(p->fnshtime-p->prio);
t+=((float)(p->fnshtime-p->prio)/p->needtime1);
printf("进程%s的完成时间为:%d\t周转时间为:%d\t带权周转时间为:%f\n",p->name,p->fnshtime-1,p->fnshtime-p->prio-1,(float)(p->fnshtime-1-p->prio)/p->needtime1);
p=p->next;
}
}
printf("平均周转时间为:%f\n",(float)n/m);
printf("平均带权周转时间为:%f\n",(float)t/m);
}
void insert1(PCB *q)
{
PCB *p1,*s,*r;
int b;
s=q;
p1=ready;
r=p1;
b=1;
while((p1!=NULL)&&b)
if(p1->prio>=s->prio)
{
r=p1;
p1=p1->next;
}
else
b=0;
if(r!=p1)
{ r->next=s;
s->next=p1;}
else
{ s->next=p1;
ready=s; }
}
void PRISCH()
{
int i=0;
while(run!=NULL&&run->prio>=0)
{
i++;
run->cputime=run->cputime+1;
run->needtime=run->needtime-1;
run->prio=run->prio-3;
if(run->needtime==0)
{
run->fnshtime=i;
run->next=finish;
finish=run;
run->prio=0;
run->state='F';
run=NULL;
if(ready!=NULL)
firstin();
}
else
if((ready!=NULL)&&(run->prio<ready->prio))
{
run->state='W';
insert1(run);
firstin();
}
print1();
}
}
void print2()
{
PCB *p;
printf("\n name cputime needtime state\n");
if(run!=NULL)
printf(" %-10s%-10d%-10d %c\n",run->name,run->cputime,run->needtime,run->state);
p=ready;
while(p!=NULL)
{ printf(" %-10s%-10d%-10d %c\n",p->name,p->cputime,p->needtime,p->state);
p=p->next;
}
p=finish;
while(p!=NULL)
{ printf(" %-10s%-10d%-10d %c\n",p->name,p->cputime,p->needtime,p->state);
p=p->next;
}
//getch();
}
void insert2(PCB *q)
{
int e;
PCB *a,*b,*c;
b=q;
a=ready;
c=a;
e=1;
while((a!=NULL)&&e)
{
if(b->needtime>=a->needtime)
{
c=a;
a=a->next;
}
else
e=0;
if(c!=a)
{
c->next=b;
b->next=a;
}
else
{
b->next=a;
ready=b;
}
}
}
void shortfirst()
{
int i=0;
//while(run->addrtime>i)
// i++;
while(run!=NULL)
{
i++;
run->cputime++;
run->needtime--;
if(run->needtime==0)
{
run->fnshtime=i;
run->next=finish;
finish=run;
run->state='F';
run=NULL;
if(ready!=NULL)
{
run=ready;
run->state='R';
ready=ready->next;
}
}
print2();
}
}
void print3()
{
PCB *p;
printf("\n name comtime needtime fishtime state\n");
if(run!=NULL)
printf(" %-10s%-10d%-10d%-10d %c\n",run->name,run->prio,run->needtime,run->fnshtime,run->state);
p=ready;
while(p!=NULL)
{ printf(" %-10s%-10d%-10d%-10d %c\n",p->name,p->prio,p->needtime,p->fnshtime,p->state);
p=p->next;
}
p=finish;
while(p!=NULL)
{ printf(" %-10s%-10d%-10d%-10d %c\n",p->name,p->prio,p->needtime,p->fnshtime,p->state);
p=p->next;
}
//getch();
}
void insert3(PCB *q)
{
int e;
PCB *a,*b,*c;
b=q;
a=ready;
c=a;
e=1;
while((a!=NULL)&&e)
{
if(b->prio>=a->prio)
{
c=a;
a=a->next;
}
else
e=0;
if(c!=a)
{
c->next=b;
b->next=a;
}
else
{
b->next=a;
ready=b;
}
}
}
void FCFS()
{
int i=0;
while(run->prio>i)
i++;
while(run!=NULL)
{
i++;
run->cputime++;
run->needtime--;
if(run->needtime==0)
{
run->fnshtime=i;
run->next=finish;
finish=run;
run->state='F';
run=NULL;
if(ready!=NULL)
{
run=ready;
run->state='R';
ready=ready->next;
}
}
print3();
}
}
void create(int choice)
{
PCB *p;
int i,time,time2;
char na[5];
ready=NULL;
finish=NULL;
run=NULL;
for(i=1;i<=m;i++)
{
//p=malloc(sizeof(PCB));
p=new PCB;
if((choice==1)||(choice==2))
{
printf("输入第%d个进程名和需要时间:\n",i);
scanf("%s%d",na,&time);
strcpy(p->name,na);
p->cputime=0;
p->needtime=time;
p->needtime1=time;
p->fnshtime=0;
p->state='W';
p->prio=50-time;
}
else
{
printf("输入第%d个进程名,达到时间和需要时间!\n",i);
scanf("%s%d%d",na,&time,&time2);
strcpy(p->name,na);
p->cputime=0;
p->fnshtime =0;
p->prio=time;
p->needtime=time2;
p->needtime1=time2;
p->state='W';
}
if(ready!=NULL){
if(choice==1)insert1(p);
else if(choice==2)insert2(p);
else insert3(p);
}
else
{
p->next=ready;
ready=p;
tail=p;
}
}
printf("进程调度过程如下:\n");
if(choice==1)
print1();
if(choice==2)
print2();
else if(choice==3)
print3();
else
{}
run=ready;
ready=ready->next;
run->state='R';
}
void jinchengguanli()
{
int a=1;
printf("1.优先数调度算法\n2.短作业优先调度算法\n3.先到先服务\n0.退出请选择:");
scanf("%d",&choice);
while(a)
{
if(choice==1)
{
printf("请输入进程的个数:");
scanf("%d",&m);create(choice);
PRISCH();
print4();
printf("1.优先数调度算法\n2.短作业优先调度算法\n3.先到先服务\n0.退出请选择:");
scanf("%d",&choice);
}
else if(choice==2)
{
printf("请输入进程的个数:");
scanf("%d",&m);create(choice);
shortfirst();print4();
printf("1.优先数调度算法\n2.短作业优先调度算法\n3.先到先服务\n0.退出请选择:");
scanf("%d",&choice);
}
else if(choice==3)
{
printf("请输入进程的个数:");
scanf("%d",&m);create(choice);
FCFS();print4();
printf("1.优先数调度算法\n2.短作业优先调度算法\n3.先到先服务\n0.退出请选择:");
scanf("%d",&choice);
}
else break;
}
}
五、运行结果
1.优先数调度算法
2.短作业优先算法
3.先来先服务算法
六、实习心得
通过本次实习,进行操作系统的模拟实现,有小组分工实现进程管理,存储管理,设备管理和文件管理。其中我负责的是进程管理,要实现的进程管理算法:先来先服务算法、短作业优先算法和高响应比优先算法,这几个原理以前学的时候感觉挺简单,但实现起来就有些困难,最后,通过网络查询和同学的帮助终于实现了。通过本次实习,对编程有新的感触和认识。希望在今后的学习和生活中多加练习和实践,有更大的提高!!