实验四文件系统实验
一 . 目的要求
1、用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。
2、要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。
二 . 例题:
1、设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。
2、程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)。
3、为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。
4、算法与框图:
①因系统小,文件目录的检索使用了简单的线性搜索。
②文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。
③程序中使用的主要设计结构如下:
主文件目录和用户文件目录( MFD、UFD)
打开文件目录( AFD)(即运行文件目录)
文件系统算法的流程图如下:
三 . 实验题:
1、增加 2~3个文件操作命令,并加以实现。(如移动读写指针,改变文件属性,更换文件名,改变文件保护级别)。
#include
#include
#include
#include
#define MAXSIZE 100
#define ADDSIZE 50
#define PT elem+l-> length
#define N 4
typedef struct term{/*班级和学期的结构体*/
char class1[10];
char term1[10];
}term;
typedef struct student{/*学生成绩信息的结构体*/
term st;/*班级和学期结构体放于此结构体中*/
char num[10];
char name[12];
float course[4];
float total;
float average;
int bit;
}lnode,*stu;
typedef struct{
lnode *elem;/*指向上个结构体的指针*/
int size;/*最大能放lnode结构体成员的个数*/
int length;/*当前长度*/
}sqack,*sq;
sqack *l;
void init(void)/*动态分配存储空间*/
{
l-> elem=(stu)malloc(MAXSIZE*sizeof(lnode));
l-> length =0;
l-> size=MAXSIZE;
}
void input(void)/*输入学生的信息*/
{
lnode *newbase,*p;
char cla[10],ter[10],ch;
int n,i;
if(l-> length> =l-> size){
newbase=(stu)realloc(l-> elem,(l-> size +ADDSIZE)*sizeof(lnode));/*追加存储空间*/
l-> elem =newbase;
l-> size +=ADDSIZE;
}
p=l-> elem;
do
{
printf( "输入班级和学期(学期用这种格式,如2005年上学期2005 1,2005年下学期2005 2;先输入班级,回车后再输入学期)\n ");
gets(cla);
gets(ter);
printf( "要输入多少个名单?");
scanf( "%d ",&n);
printf( "输入学生的成绩\n学号\t姓名\t科目1\t科目2\t科目3\t科目4\n ");
for(i=0;i { scanf( "%s%s%d%d%d%d ",p-> num ,p-> name,p-> course[0],p-> course[1],p-> course[2],p-> course[3]); strcpy(p-> st.class1,cla); strcpy(p-> st.term1,ter); ++l-> length ; } printf( "要继续吗?(y/n) "); ch=getchar();}while(ch== 'Y '||ch== 'y '); } void change()/*修改学生的信息*/ { lnode *p; lnode e; int flag=1,i; char s1[10],num1[10]; printf( "输入学期和学号(输入学期以后按回车再输入学号):\n "); gets(s1); gets(num1); p=l-> elem ; while(p <=(l-> elem+l-> length ) && flag==1)/*查找要修改的学生的信息*/ { if(strcmp(p-> num,num1)==0&&strcmp(p-> st.term1,s1)==0) flag=0;/*找到了*/ p++; } p--; if(flag==1) printf( "找不到此学号!\n "); printf( "%s %s ",p-> num,p-> name); for(i=0;i printf( "%d ",p-> course[i]); printf( "\n "); printf( "输入修改信息\n "); scanf( "%s%s%s%s ",e.st.class1,e.st.term1,&e.num,https://www.wendangku.net/doc/273992797.html,); for(i=0;i scanf( "%d ",&e.course[i]); *p=e; } void same(char *t1,char *t2,lnode *t,int *k) /*把学期和班级相同的学生信息放在结构体数组tt中*/ { int i=0; lnode *p,*q; q=t; p=l-> elem ; while(p <=l-> elem+l-> length ) { if(strcmp(p-> st.term1,t1)==0&&strcmp(p-> st.class1 ,t2)==0) { *q=*p;q++; i++; } p++; } *k=i; } void sort(lnode *p,int *k)/*按学生成绩从高到低排序函数*/ { int i; lnode *q,temp; for(q=p;q { q-> total =0; for(i=0;i q-> total =q-> total +q-> course [i]; q-> average =q-> total /N; } for(i=0;i <*k-1;i++) for(q=p;q if(q-> total <(q+1)-> total) { temp=*q;*q=*(q+1);*(q+1)=temp; } } void print(lnode *q,int *k)/*输出学生的成绩*/ { lnode *p; p=q; for(p=q;p { printf( "%s %s ",p-> num,p-> name); for(int i=0;i printf( "%d ",p-> course[i]); printf( "%d %f ",p-> total,p-> average); printf( "\n "); } } void stat()/*统计学生的成绩*/ { lnode tt[50]; char ter[10],clas[10]; int i,k; printf( "请输入学期和班级(输入学期后按回车再输入班级):\n "); for(i=0;ter[i]!= '\n ';i++) ter[i]=getchar(); for(i=0;clas[i]!= '\n ';i++) clas[i]=getchar(); same(ter,clas,tt,&k);/*把学期和班级相同的学生信息放在结构体数组tt中*/ sort(tt,&k);/*按学生成绩从高到低排序函数*/ print(tt,&k);/*输出学生的成绩*/ } void search1()/*按学号查*/ { lnode *p; char ter1[10]; int i,flag=1; p=l-> elem; printf( "输入学号:"); gets(ter1); for(p=l-> elem;p { if(strcmp(p-> num,ter1)==0) { flag=0; printf( "%s %s ",p-> st.term1,p-> st.class1); printf( "%s %s ",p-> num,p-> name); for(i=0;i printf( "%d ",p-> course[i]); printf( "%d %3.1f ",p-> total,p-> average); printf( "\n "); } } if(flag) printf( "没有找到!"); } void search2()/*按姓名查*/ { lnode *p; char ter1[10]; int i,flag=1; p=l-> elem; printf( "输入姓名:"); gets(ter1); for(p=l-> elem;p { if(strcmp(p-> name,ter1)==0) { flag=0; printf( "%s %s ",p-> st.term1,p-> st.class1); printf( "%s %s ",p-> num,p-> name); for(i=0;i printf( "%d ",p-> course[i]); printf( "%d %f ",p-> total,p-> average); printf( "\n "); } } if(flag) printf( "没有找到!") ; } void search()/*查找学生的成绩*/ { char ch; do { printf( "1 按学号查询\n2按姓名查询\n "); ch=getchar(); switch(ch) { case '1 ': search1(); break; case '2 ': search2(); break; default: printf( "错误!\n "); } printf( "要继续查找吗?(y/n) "); ch=getchar(); } while(ch== 'y ' || ch== 'Y '); } void fail()/*查找不及格及学生名单*/ { int i; lnode *p; for(p=l-> elem;p { for(i=0;i if(p-> course[i] <60) { printf( "%s %s ",p-> st.class1,p-> st.term1); for(i=0;i printf( "%d ",p-> course[i]); printf( "%d %f ",p-> total,p-> average); printf( "\n ");}} } void output()/*按班级输出学生的成绩单*/ { lnode tt[50]; int k; char clas[10],ter1[10]; printf( "输入要查询的班级和学期(输入班级后按回车输入学期):\n "); gets(clas); gets(ter1); same(ter1,clas,tt,&k);/*把学期和班级相同的学生信息放在结构体数组tt中*/ print(tt,&k);/*输出学生的成绩*/ } int main() { char ch; do { printf( "请选择:\n "); printf( "1 对学生成绩的录入\n2 对学生成绩的修改\n3 统计学生成绩\n4 查询学生成绩\n5查找不及格科目及学生名单\n6 按班级输出学生成绩单\n "); ch=getchar(); switch(ch) { case '1 ': input();break; case '2 ':change();break; case '3 ':stat();break; case '4 ':search();break; case '5 ':fail();break; case '6 ':output();break; default:printf( "错误!\n "); } printf( "要继续吗?(y/n) "); ch=getchar(); }while(ch== 'y '||ch== 'Y '); return 0; getch(); } 2、编一个通过屏幕选择命令的文件管理系统,每屏要为用户提供足够的选择信息,不需要打入冗长的命令。 #include #include #include //主文件结构体 struct MasterFile{ char username[20]; //用户名 char password[20]; //用户名密码 char flag; //标志 struct MasterFile *next; }; //用户文件结构体 struct UserFile{ int fnum; //文件编号 char fname[20]; //文件名 int flength; //文件长度 char flag; //标志 char fpw[20]; //文件保护码 struct UserFile *link; }; //全局变量 int shoudsave; //存储标记 int usingnum; //当前用户标记 struct MasterFile MFD[20]; //主目录 struct UserFile UFD[20][20]; //用户目录 //寻找主目录空闲区 struct MasterFile*MoveMFDToLast() { for(int i=0;i<20;i++){ if(MFD[i].flag==0) usingnum=i; return &MFD[i]; } return NULL; } //查找用户 struct MasterFile*SearchMFD(char str[]){ for(int i=0;i<20;i++){ if(strcmp(str,MFD[i].username)==0){ usingnum=i; return &MFD[i]; } } return NULL; } //寻找用户目录空闲区 struct UserFile *MoveUFDToLast(){ for(int i=0;i<20;i++){ if(UFD[usingnum][i].flag==0) return &UFD[usingnum][i]; } return NULL; } //查找用户文件 struct UserFile *SearchUFD(int num){ for(int i=0;i<20;i++){ if(UFD[usingnum][i].fnum==num) return &UFD[usingnum][i]; } return NULL; } //删除用户文件目录 void LeftMoveUFD(int num){ for(int i=0;i<20;i++){ if(UFD[usingnum][i].fnum==num){ for(int j=i;j<19;j++){ UFD[usingnum][i].flag=UFD[usingnum][i+1].flag; UFD[usingnum][i].flength=UFD[usingnum][i+1].flength; strcpy(UFD[usingnum][i].fname,UFD[usingnum][i+1].fname); UFD[usingnum][i].fnum=UFD[usingnum][i+1].fnum; strcpy(UFD[usingnum][i].fpw,UFD[usingnum][i+1].fpw); UFD[usingnum][i].link=UFD[usingnum][i+1].link; } } } } //用户登陆 void Login(){ char flag1,flag2,flag3; char str1[20],str2[20],str3[20],str4[20]; struct MasterFile *p; printf("你是已有用户吗(y/n)?"); scanf("%s",&flag1); if(flag1=='n'){ //新用户登录 printf("请创建新的用户:(y/n)"); scanf("%s",&flag2); if(flag2=='n'){ printf("你已退出了系统!\n"); exit(1); }else{ printf("请输入你的用户名:"); scanf("%s",&str1); printf("请输入口令:"); scanf("%s",&str2); p=MoveMFDToLast(); strcpy(p->username,str1); strcpy(p->password,str2); p->flag=1; printf("%d",MFD[usingnum].flag); p->next=NULL; shoudsave=1; //存储标记 } }else{ //旧用户登录 while(1){ printf("请输入你的用户名:"); //输入用户名 scanf("%s",&str3); p=SearchMFD(str3); if(p==NULL){ printf("对不起,你输入的用户名不存在!\n"); printf("继续(y)还是放弃(n)?"); scanf("%s",&flag3); if(flag3=='y') continue; else{ printf("你已退出了系统!\n"); exit(1); } }else{ while(1){ printf("请输入口令:"); //输入口令 scanf("%s",&str4); if(strcmp(str4,p->password)!=0){ printf("对不起,你输入的口令不正确,请重新输入.\n"); continue; }else break; } }break; } } } //菜单 void menu(){ printf("\n*********************************************************** *********************"); printf("\t1列文件目录\t\t\t\t\t2创建文件\n"); printf("\t3删除文件\t\t\t\t\t4读文件\n"); printf("\t5写文件\t\t\t\t\t\t0退出系统\n"); printf("************************************************************* *******************\n"); } //列文件目录 void Dir(){ if(MFD[usingnum].next==0) printf("目前你不存在任何文件!\n"); else{ for(int i=0;i<20;i++){ if(UFD[usingnum][i].flag==1) printf("文件编号\t%d\t文件名\t%s\t文件长度\t%d\t保护码 \t%s\n",UFD[usingnum][i].fnum,UFD[usingnum][i].fname,UFD[usingnum][i] .flength,UFD[usingnum][i].fpw); } } } //创建文件 void Create(){ FILE *fp; int num; struct UserFile *f; char str1[20],str2[20]; printf("请输入你要创建的文件名:"); //输入文件信息 scanf("%s",&str1); printf("请输入文件编号:"); scanf("%d",&num); printf("请输入文件保护码:"); scanf("%s",&str2); fp=fopen(str1,"w"); //创建文件 f=MoveUFDToLast(); //寻找用户目录空闲区 if(&UFD[usingnum][0]==f) //连接主目录 MFD[usingnum].next=(struct MasterFile*)f; f->link=(struct UserFile*)fp; //设置用户目录 MFD[usingnum].next=(struct MasterFile*)&UFD[usingnum][0]; strcpy(f->fname,str1); strcpy(f->fpw,str2); f->fnum=num; f->flength=0; f->flag=1; fclose(fp); shoudsave=1; //设置存储标记 printf("文件已创建!\n"); } //删除文件 void Delete(){ struct UserFile *f; int num; printf("请输入你要删除的文件编号:"); scanf("%d",&num); f=SearchUFD(num); //查找用户文件 if(f==NULL) { printf("你要删除的文件不存在!\n"); }else{ LeftMoveUFD(num); //删除用户文件目录 printf("文件已删除!\n"); } shoudsave=1; //设置存储标记 } //读文件 void Read(){ char ch; struct UserFile *f; FILE *fp; int num; printf("请输入你要读的文件的编号:"); scanf("%d",&num); f=SearchUFD(num); //查找文件 if(f==NULL){ printf("你输入的文件不存在!\n"); }else{ if((fp=fopen(f->fname,"r"))==NULL){ //打开指定文件printf("不能打开该文件!\n"); exit(0); } } ch=fgetc(fp); //输出文件内容 while(ch!=EOF){ putchar(ch); ch=fgetc(fp); } printf("\n"); fclose(fp); //关闭文件 printf("文件已读完毕!\n"); } //写文件 void Write(){ char ch; struct UserFile *f; FILE *fp; int num; printf("请输入你要写的文件的编号:"); scanf("%d",&num); f=SearchUFD(num); //查找文件 if(f==NULL){ printf("你输入的文件不存在!\n"); }else{ if((fp=fopen(f->fname,"wr"))==NULL){ //打开指定文件printf("不能打开该文件!\n"); exit(0); } } printf("请按字符输入内容(以'#'表示结束符)"); //写入文件 scanf("%s",&ch); while(ch!='#'){ fwrite(&ch,1,1,fp); scanf("%s",&ch); } fclose(fp); //关闭文件 shoudsave=1; //设置存储标记 printf("文件写入完毕!\n"); } //保存 void Save(){ FILE *fpm,*fpu; int flag=1,count=0; fpm=fopen("F:\\MasterFile.txt","wb"); //打开主文件 if(fpm==NULL){ printf("\n提示:重新打开主文件信息文件时发生错误!\n"); exit(1); } for(int i=0;i<20;i++) fwrite(&MFD[i],sizeof(struct MasterFile),1,fpm); //保存主文件目录信息fclose(fpm); printf("主文件目录信息保存完毕!\n"); fpu=fopen("F:\\UserFile.txt","wb"); //打开用户文件 if(fpu==NULL){ printf("\n提示:重新打开用户目录信息文件时发生错误!\n"); exit(1); } for(int j=0;j<20;j++) //保存用户文件目录信息 fwrite(&UFD[j],sizeof(struct UserFile),20,fpu); fclose(fpu); printf("用户文件目录信息保存完毕!\n"); } //主函数 void main(){ FILE *fpm,*fpu; //文件指针 int sel; char ch; char jian; printf("\t\t\t\t文件管理系统\n\t\t\t\t\n"); fpm=fopen("D:\\MasterFile.txt","rb"); //打开主文件目录信息文件 if(fpm==NULL) { printf("\n提示:主文件目录信息文件还不存在,是否创建?(y/n)\n"); scanf("%s",&jian); if(jian=='y'||jian=='Y') fpm=fopen("D:\\MasterFile.txt","wb"); //创建主文件目录的文件 else exit(0); } fpu=fopen("D:\\UserFile.txt","rb"); //打开用户文件目录信息文件 if(fpu==NULL){ printf("\n提示:用户文件目录信息文件还不存在,是否创建?(y/n)\n"); scanf("%s",&jian); if(jian=='y'||jian=='Y') fpu=fopen("D:\\UserFile.txt","wb"); //创建用户文件目录的文件 else exit(0); } printf("文件正在打开,请稍等..."); for(int i=0;i<20;i++) //读取主文件目录信息 fread(&MFD[i],sizeof(struct MasterFile),1,fpm); //将文件的内容放入接点中 fclose(fpm); // 关闭文件 while(!feof(fpu)){ //读取用户目录文件信息 for(int i=0;i<20;i++){ if(fread(&UFD[i][0],sizeof(struct UserFile),20,fpu)) //将文件的内容放入接点中 MFD[i].next=(struct MasterFile*)&UFD[i][0]; } } fclose(fpu); //关闭文件 printf("\n文件已导入完毕!\n"); Login(); //用户登录 while(1) { //菜单操作 menu(); printf("请你选择操作:"); scanf("%d",&sel); if(sel==0){ //保存文件信息 if(shoudsave==1){ getchar(); printf("\n资料已经改动,是否将改动保存到文件中(y/n)?\n"); scanf("%c",&ch); if(ch=='y'||ch=='Y') Save(); } printf("\n你已经退出系统,再见!\n"); break; } switch(sel){ case 1:Dir(); break; //列文件目录 case 2:Create(); break; //创建文件 case 3:Delete(); break; //删除文件 case 4:Read(); break; //读文件 case 5:Write(); break; //写文件 default: printf("你输的选项有误,请重新输入!\n"); break; } } } 3、设计一个树型目录结构的文件系统,其根目录为 root,各分支可以是目录,也可以是文件,最后的叶子都是文件。 #include #include #include #include #include #define FILENAME_LEN 21 #define INPUT_LEN 81 #define COMMAND_LEN 11 //结点结构 struct FileNode { char filename[FILENAME_LEN];//文件名/目录名 int isdir;//目录文件识别标志 int i_nlink;//文件的链接数 int adr;//文件的地址 struct FileNode *parent, *child;//指向父亲的指针和指向左孩子的指针 struct FileNode *sibling_prev, *sibling_next;//指向前一个兄弟的指针和指向 //后一个兄弟的指针. }; void Init();//初始化文件树 int ParseCommand();//接受输入的命令并把其分解成操作名和路径文件名void ExecuteCommand();//执行命令 int cdComd();//处理cd命令 int editComd();//处理edit命令创建文件 int delComd();//处理del命令删除文件 int rdComd();//处理rd命令/删除目录 int dirComd();//处理dir命令 int mdComd();//处理md命令创建目录 int FindPath(char *ph);//寻找参数ph所指向的路径 //从参数Para2中找到要建立或删除的文件、目录名,并把指针指向其父亲结点int FindFilename(char Para2[]); struct FileNode* CreateFileNode(char filename[],int isdir,int i_nlink);//创建结点 int GetInput(char* buffer,unsigned int buffer_len);//获取输入 int CheckCommand();//命令检查 int GetDir(int begin,char* path,char* curDir);//获取路径 void Trim(char* str); struct FileNode * cp, *tp, *root,*upper; char path[INPUT_LEN-COMMAND_LEN];//记录当前走过的路径 char curpath[INPUT_LEN-COMMAND_LEN],Para1[COMMAND_LEN], Para2[INPUT_LEN-COMMAND_LEN],tmppath[INPUT_LEN-COMMAND_LEN]; char filename[FILENAME_LEN],dirname[FILENAME_LEN],tmp; int i,j; //主函数 int main() { printf("<<<*****************09208041 杜耀军树型目录结构的文件系统*****************>>>\n"); Init();//初始化文件树 while(1) { if(ParseCommand())//分解命令 ExecuteCommand();//执行命令 } } //执行命令子函数 void ExecuteCommand() { int sign; //根据参数Para1调用相应的功能处理模块 if(strcmp(Para1,"cd")==0) sign=cdComd(); //cd命令 else if(strcmp(Para1,"edit")==0) sign=editComd(); //edit命令 else if(strcmp(Para1,"del")==0) sign=delComd(); //del命令 else if(strcmp(Para1,"dir")==0) sign=dirComd(); //dir命令 else if(strcmp(Para1,"md")==0) sign=mdComd(); //md命令 else if(strcmp(Para1,"rd")==0) sign=rdComd(); //rd命令 else if(strcmp(Para1,"exit")==0) exit(0); //exit命令 else printf("命令错误,请重试\n"); //命令输入不正确,报错 } //创建结点 struct FileNode* CreateFileNode(char filename[],int isdir,int i_nlink) { //申请结点空间 struct FileNode* node=(struct FileNode*)malloc(sizeof(struct FileNode)); //相应内容赋初值 strcpy(node->filename,filename); node->isdir=isdir; node->i_nlink=i_nlink; node->parent=NULL; node->child=NULL; node->sibling_prev=NULL; node->sibling_next=NULL; return node; } //初始化文件树 void Init() { struct FileNode *binNode,*usrNode, *unixNode,*etcNode,*libNode,*userNode, *binNode2,*liuNode,*sunNode,*ftiNode; strcpy(path,"/"); //根目录写入当前路径 //创建文件树的结点 binNode=CreateFileNode("bin",1,0); usrNode=CreateFileNode("usr",1,0); unixNode=CreateFileNode("unix",0,0); etcNode=CreateFileNode("etc",1,0); libNode=CreateFileNode("lib",1,0); userNode=CreateFileNode("user",1,0); binNode2=CreateFileNode("bin",1,0); liuNode=CreateFileNode("liu",1,0); sunNode=CreateFileNode("sun",1,0); ftiNode=CreateFileNode("fti",1,0); cp=tp=root=CreateFileNode("/",1,0); //结点相应内容赋值 root->parent=NULL; root->child=binNode; root->sibling_prev=root->sibling_next=NULL; binNode->parent=root; binNode->child=NULL; binNode->sibling_prev=NULL; binNode->sibling_next=usrNode; usrNode->parent=NULL; usrNode->child=libNode; usrNode->sibling_prev=binNode; usrNode->sibling_next=unixNode; unixNode->parent=NULL; unixNode->child=NULL; unixNode->sibling_prev=usrNode; unixNode->sibling_next=etcNode; etcNode->parent=NULL; etcNode->child=NULL; etcNode->sibling_prev=unixNode; etcNode->sibling_next=NULL; libNode->parent=usrNode; libNode->child=liuNode; libNode->sibling_prev=NULL; libNode->sibling_next=userNode; userNode->parent=NULL; userNode->child=NULL; userNode->sibling_prev=libNode; userNode->sibling_next=binNode2; binNode2->parent=NULL; binNode2->child=NULL; binNode2->sibling_prev=userNode; binNode2->sibling_next=NULL; liuNode->parent=libNode; liuNode->child=NULL; liuNode->sibling_prev=NULL; liuNode->sibling_next=sunNode; sunNode->parent=NULL; sunNode->child=NULL; sunNode->sibling_prev=liuNode; sunNode->sibling_next=ftiNode; ftiNode->parent=NULL; ftiNode->child=NULL; ftiNode->sibling_prev=sunNode; ftiNode->sibling_next=NULL; } //获取文件或目录名,并把指针指向其父亲结点 int FindFilename(char Para2[]) { i=strlen(Para2)-1; j=0; while(Para2[i]!='/'&& i>=0) { filename[j]=Para2[i]; i--; j++; } filename[j]='\0';//获得逆序的文件或目录名,存入filename中 if(i<0) Para2[i+1]='\0'; else Para2[i]='\0'; j--; //filename逆转,获得正确的文件或目录名 for(i=0;i { tmp=filename[i]; filename[i]=filename[j]; filename[j]=tmp; } //查找路径 if(strlen(Para2)>0) { int sign=FindPath(Para2); if(sign==0) return 0; } return 1; } //缓冲区安全输入子函数 //如果输入超过buffer_len,则截取前buffer_len-1长度的输入,//buffer_len处字符用'/0'代替 int GetInput(char* buffer,unsigned int buffer_len) { int count=0; while(count { if((buffer[count]=getchar())==10) { buffer[count]='\0'; return count; } count++; } while(getchar()!=10); buffer[buffer_len-1]='\0'; return -1; } //分解命令子函数 int ParseCommand() { char Inputs[INPUT_LEN]; int i=0,j=0,k=0,ch; printf("%s>",path); //获取输入 if(GetInput(Inputs,INPUT_LEN)==-1) { printf("输入行太长。\n"); return 0; } Para1[0]=Para2[0]='\0'; //获取参数Para1,即操作名 while(Inputs[i]!=' '&&Inputs[i]!='\0' && i Para1[i]=Inputs[i]; i++; }//while Para1[i]='\0'; //输入命令太长 if(i==(COMMAND_LEN-1))return 1; //获取参数2,即路径文件名 if(Inputs[i]!='\0') { while(Inputs[i]==' ' && i j=0; while(Inputs[i]!='\0' && i { Para2[j]=Inputs[i]; i++; j++; } Para2[j]='\0'; } Trim(Para1); Trim(Para2); //将操作名全部转换成小写字母 for(k=0;k { ch=tolower((int)Para1[k]); Para1[k]=ch; } return 1; 嵌入式系统实验报告(二) --嵌入式文件系统的构建 138352019陈霖坤一实验目的 了解嵌入式操作系统中文件系统的类型和作用 了解JFFS2文件系统的优点及其在嵌入式系统中的作用 掌握利用Busybox软件制作嵌入式文件系统的方法 掌握嵌入式linux文件系统的挂载过程 二实验内容与要求 编译BusyBox,以BusyBox为基础,构建一个适合的文件系统; 制作ramdisk文件系统映像,用你的文件系统启动到正常工作状态; 研究NFS作为根文件系统的启动过程。 三Busybox介绍 BusyBox最初是由Bruce Perens在1996年为Debian GNU/Linux安装盘编写的,其原始构想是希望在一张软盘上能放入一个开机系统,以作为急救盘和安装盘。后来它变成了嵌入式Linux设备和系统和Linux发布版安装程序的实质标准,因为每个Linux可执行文件需要数Kb的空间,而集成两百多个程序的BusyBox可以节省大量空间。Busybox集成了包括mini-vi编辑器、/sbin/init、文件操作、目录操作、系统配置等应用程序。 Busybox支持多种体系结构,可以选择静态或动态链接,以满足不同需要。 四linux文件系统 文件系统是对一个存储设备上的数据和元数据进行组织的机制,linux文件系统接口设计为分层的体系结构,从而将用户接口层、文件系统实现层和操作存储设备的驱动程序分隔开。 在文件系统方面,linux可以算得上操作系统中的“瑞士军刀”。Linux支持许多种文件系统,从日志型文件系统到集群文件系统和加密文件系统,而且对于使用标准的和比较奇特的文件系统以及开发文件系统来说,linux是极好的平台,这得益于linux内核中的虚拟文件系统(VFS,也称虚拟文件系统交换器)。 文件结构 Windows的文件结构是多个并列的树状结构,不同的磁盘分区各对应一个树。Linux的文件结构是单个的树,最上层是根目录,其它目录都从根目录生成。不同的linux发行版集 实验一进程管理 一、目的 进程调度是处理机管理的核心内容。本实验要求编写和调试一个简单的进程调度程序。通过本实验加深理解有关进程控制块、进程队列的概念,并体会和了解进程调度算法的具体实施办法。 二、实验内容及要求 1、设计进程控制块PCB的结构(PCB结构通常包括以下信息:进程名(进程ID)、进程优先数、轮转时间片、进程所占用的CPU时间、进程的状态、当前队列指针等。可根据实验的不同,PCB结构的内容可以作适当的增删)。为了便于处理,程序中的某进程运行时间以时间片为单位计算。各进程的轮转时间数以及进程需运行的时间片数的初始值均由用户给定。 2、系统资源(r1…r w),共有w类,每类数目为r1…r w。随机产生n进程P i(id,s(j,k),t),0<=i<=n,0<=j<=m,0<=k<=dt为总运行时间,在运行过程中,会随机申请新的资源。 3、每个进程可有三个状态(即就绪状态W、运行状态R、等待或阻塞状态B),并假设初始状态为就绪状态。建立进程就绪队列。 4、编制进程调度算法:时间片轮转调度算法 本程序用该算法对n个进程进行调度,进程每执行一次,CPU时间片数加1,进程还需要的时间片数减1。在调度算法中,采用固定时间片(即:每执行一次进程,该进程的执行时间片数为已执行了1个单位),这时,CPU时间片数加1,进程还需要的时间片数减1,并排列到就绪队列的尾上。 三、实验环境 操作系统环境:Windows系统。 编程语言:C#。 四、实验思路和设计 1、程序流程图 2、主要程序代码 //PCB结构体 struct pcb { public int id; //进程ID public int ra; //所需资源A的数量 public int rb; //所需资源B的数量 public int rc; //所需资源C的数量 public int ntime; //所需的时间片个数 public int rtime; //已经运行的时间片个数 public char state; //进程状态,W(等待)、R(运行)、B(阻塞) //public int next; } ArrayList hready = new ArrayList(); ArrayList hblock = new ArrayList(); Random random = new Random(); //ArrayList p = new ArrayList(); int m, n, r, a,a1, b,b1, c,c1, h = 0, i = 1, time1Inteval;//m为要模拟的进程个数,n为初始化进程个数 //r为可随机产生的进程数(r=m-n) //a,b,c分别为A,B,C三类资源的总量 //i为进城计数,i=1…n //h为运行的时间片次数,time1Inteval为时间片大小(毫秒) //对进程进行初始化,建立就绪数组、阻塞数组。 public void input()//对进程进行初始化,建立就绪队列、阻塞队列 { m = int.Parse(textBox4.Text); n = int.Parse(textBox5.Text); a = int.Parse(textBox6.Text); b = int.Parse(textBox7.Text); c = int.Parse(textBox8.Text); a1 = a; b1 = b; c1 = c; r = m - n; time1Inteval = int.Parse(textBox9.Text); timer1.Interval = time1Inteval; for (i = 1; i <= n; i++) { pcb jincheng = new pcb(); jincheng.id = i; jincheng.ra = (random.Next(a) + 1); jincheng.rb = (random.Next(b) + 1); jincheng.rc = (random.Next(c) + 1); jincheng.ntime = (random.Next(1, 5)); jincheng.rtime = 0; 山东大学操作系统实验报告4进程同步实验 计算机科学与技术学院实验报告 实验题目:实验四、进程同步实验学号: 日期:20120409 班级:计基地12 姓名: 实验目的: 加深对并发协作进程同步与互斥概念的理解,观察和体验并发进程同步与互斥 操作的效果,分析与研究经典进程同步与互斥问题的实际解决方案。了解 Linux 系统中 IPC 进程同步工具的用法,练习并发协作进程的同步与互斥操作的编程与调试技术。 实验内容: 抽烟者问题。假设一个系统中有三个抽烟者进程,每个抽烟者不断地卷烟并抽烟。抽烟者卷起并抽掉一颗烟需要有三种材料:烟草、纸和胶水。一个抽烟者有烟草,一个有纸,另一个有胶水。系统中还有两个供应者进程,它们无限地供应所有三种材料,但每次仅轮流提供三种材料中的两种。得到缺失的两种材料的抽烟者在卷起并抽掉一颗烟后会发信号通知供应者,让它继续提供另外的两种材料。这一过程重复进行。请用以上介绍的 IPC 同步机制编程,实现该问题要求的功能。 硬件环境: 处理器:Intel? Core?i3-2350M CPU @ 2.30GHz ×4 图形:Intel? Sandybridge Mobile x86/MMX/SSE2 内存:4G 操作系统:32位 磁盘:20.1 GB 软件环境: ubuntu13.04 实验步骤: (1)新建定义了producer和consumer共用的IPC函数原型和变量的ipc.h文件。 (2)新建ipc.c文件,编写producer和consumer 共用的IPC的具体相应函数。 (3)新建Producer文件,首先定义producer 的一些行为,利用系统调用,建立共享内存区域,设定其长度并获取共享内存的首地址。然后设定生产者互斥与同步的信号灯,并为他们设置相应的初值。当有生产者进程在运行而其他生产者请求时,相应的信号灯就会阻止他,当共享内存区域已满时,信号等也会提示生产者不能再往共享内存中放入内容。 (4)新建Consumer文件,定义consumer的一些行为,利用系统调用来创建共享内存区域,并设定他的长度并获取共享内存的首地址。然后设定消费者互斥与同步的信号灯,并为他们设置相应的初值。当有消费进程在运行而其他消费者请求时,相应的信号灯就会阻止它,当共享内存区域已空时,信号等也会提示生产者不能再从共享内存中取出相应的内容。 运行的消费者应该与相应的生产者对应起来,只有这样运行结果才会正确。 操作系统实验报告 ' 学号: 姓名: 指导老师: 完成日期: ~ 目录 实验一 (1) 实验二 (2) 实验三 (7) 实验四 (10) 实验五 (15) 实验六 (18) 实验七 (22) \ 实验一 UNIX/LINUX入门 一、实验目的 了解 UNIX/LINUX 运行环境,熟悉UNIX/LINUX 的常用基本命令,熟悉和掌握UNIX/LINUX 下c 语言程序的编写、编译、调试和运行方法。 二、实验内容 熟悉 UNIX/LINUX 的常用基本命令如ls、who、pwd、ps 等。 练习 UNIX/LINUX的文本行编辑器vi 的使用方法 熟悉 UNIX/LINUX 下c 语言编译器cc/gcc 的使用方法。用vi 编写一个简单的显示“Hello,World!”c 语言程序,用gcc 编译并观察编译后的结果,然后运行它。 三、实验要求 按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。 四、实验程序 #include <> #include <> int main() { printf ("Hello World!\n"); return 0; } 五、实验感想 通过第一次室验,我了解 UNIX/LINUX 运行环境,熟悉了UNIX/LINUX 的常用基本命令,熟悉和掌握了UNIX/LINUX 下c 语言程序的编写、编译、调试和运行方法。 实验二进程管理 一、实验目的 加深对进程概念的理解,明确进程与程序的区别;进一步认识并发执行的实质。 二、实验内容 (1)进程创建 编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示“a“;子进程分别显示字符”b“和字符“c”。试观察记录屏幕上的显示结果,并分析原因。 (2)进程控制 修改已编写的程序,将每一个进程输出一个字符改为每一个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。 (3)进程的管道通信 编写程序实现进程的管道通信。使用系统调用pipe()建立一个管道,二个子进程P1 和P2 分别向管道各写一句话: Child 1 is sending a message! Child 2 is sending a message! 父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,再接收P2)。 三、实验要求 按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。 四、实验设计 1、功能设计 (1)进程创建 使用fork()创建两个子进程,父进程等待两个子进程执行完再运行。 (2)进程控制 使用fork()创建两个子进程,父进程等待两个子进程分别输出一句话再运行。 (3)进程的管道通信 先创建子进程1,向管道写入一句话,子进程1结束后创建子进程2,向管道写入一句话,最后父进程从管道中读出。 2、数据结构 子进程和管道。 3、程序框图 黄冈师学院 提高型实验报告 实验课题文件系统的设计与实现(实验类型:□综合性 设计性□应用性) 实验课程操作系统原理 实验时间2015-2016 第二学期 学生何正发 专业班级软件工程1401 学号07 成绩: 一、实验目的和要求 1、熟悉操作系统设计的过程,巩固操作系统的基本知识,加深对操作原理、功能及各种不同的存储管理方法理解与应用; 2、学会运用各种语言、软件开发新软件的基本方法; 3、增强实际应用能力和动手操作能力。 二、实验条件 Win7 /Windows 8.1/Linux等操作系统,装有java、C、C++、C#等语言工具的环境。 三、实验原理分析 可以选择最佳适应算法,按照从小到大的次序组成空闲区自由链,当用户作业或进程申请一个空闲区时,存储管理 程序从表头开始查找,当找到第一个満足要求的空闲区时,停止查找。如果该空闲区大于请求表中的请求长 度,将减去请求长度后的剩余空闲区部分留在可用表中。回收时,从作链中删去要回收的作业块,同时在空 闲链中插入该作业大小的空闲区,并按顺序排列 四、实验方案或步骤 1、应用环境、需求分析 本模拟系统主要针对文件的管理和操作名主要有:创建用户、文件、文件夹,读文件,写文件,执行文件,关闭文件,删除用户、文件夹、文件的功能。 创建用户、文件、文件夹:在对系统发出操作命令之前必须先登录用户,然而登录之前必须创建该用户。在创建完后,可通过登录用户来创建文件和文件夹。在创建文件时可设置文件的属性和输入文件的容。 读文件:读取任何已创建的只读或读写文件的容;如果所要读的文件不是可读文件时,系统会显示该文件不可读;如果所读文件不存在,系统会显示文件不存在。 写文件用户可写或重写读写文件中的容,并保存文件中的重写容,以供下次读取;当所要写的文件不是可写的文件时,系统会显示该文件不可写;当所要写的文件并不存在时,系统会显示该文件不存在。 中南大学信息科学与工程学院实验报告 姓名:安磊 班级:计科0901 学号: 0909090310 指导老师:宋虹 目录 课程设计内容 ----------------------------------- 3 uC/OS操作系统简介 ------------------------------------ 3 uC/OS操作系统的组成 ------------------------------ 3 uC/OS操作系统功能作用 ---------------------------- 4 uC/OS文件系统的建立 ---------------------------- 6 文件系统设计的原则 ------------------------------6 文件系统的层次结构和功能模块 ---------------------6 文件系统的详细设计 -------------------------------- 8 文件系统核心代码 --------------------------------- 9 课程设计感想 ------------------------------------- 11 附录-------------------------------------------------- 12 课程设计内容 在uC/OS操作系统中增加一个简单的文件系统。 要求如下: (1)熟悉并分析uc/os操作系统 (2)设计并实现一个简单的文件系统 (3)可以是存放在内存的虚拟文件系统,也可以是存放在磁盘的实际文件系统 (4)编写测试代码,测试对文件的相关操作:建立,读写等 课程设计目的 操作系统课程主要讲述的内容是多道操作系统的原理与技术,与其它计算机原理、编译原理、汇编语言、计算机网络、程序设计等专业课程关系十分密切。 本课程设计的目的综合应用学生所学知识,建立系统和完整的计算机系统概念,理解和巩固操作系统基本理论、原理和方法,掌握操作系统开发的基本技能。 I.uC/OS操作系统简介 μC/OS-II是一种可移植的,可植入ROM的,可裁剪的,抢占式的,实时多任务操作系统内核。它被广泛应用于微处理器、微控制器和数字信号处理器。 μC/OS 和μC/OS-II 是专门为计算机的嵌入式应用设计的,绝大部分代码是用C语言编写的。CPU 硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU 上。用户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件工具,就可以将μC/OS-II嵌入到开发的产品中。μC/OS-II 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点,最小内核可编译至2KB 。μC/OS-II 已经移植到了几乎所有知名的CPU 上。 严格地说uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。没有提供输入输出管理,文件系统,网络等额外的服务。但由于uC/OS-II良好的可扩展性和源码开放,这些非必须的功能完全 可以由用户自己根据需要分别实现。 uC/OS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等。 uC/OS操作系统的组成 μC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。如下图: 操作系统课程设计之三 设计任务:模拟OS文件系统 在任一OS(Window或者Dos;也可以是在Linux下,但要求能将结果演示给老 师看)下,建立一个大文件,把它假象成一张盘,在其中实现一个简单的模拟OS 字 ,第 ⑤、每个目录实际能放下文件或子目录30项。 ⑸、文件系统空间分配: ①、第0个盘块(1k)存放磁盘信息(可以设定为格式说明“FAT32”、盘块大小,盘块数等 内容) ②、第1个盘块起,至125盘块,共125个盘块(125k)存放FAT内容 ③、第126、127(2个)盘块,存放位示图 ④、从第128盘块至10000盘块,皆为数据(区)盘块,其逻辑编号从0开始,至 9872号数据盘块,即第0数据盘块为128号盘块,第1数据盘块为129号盘块,… ⑤、第0数据盘块(即128号盘块),存放根目录(同样只用一个盘块作根目录), 由于第0、1目录项为“.”(本目录), “..”(父目录),因此根目录下同样只能存放30个文件或目录,并且从第2个目录项开始。 ⑥、文件或子目录数据,放在第1数据盘块及以后的数据盘块中,由用户按需要使 用。 内容 ⑺、删除文件 #DelFile 文件名.扩展名,在文件所在的目录项中,将第一个字节变为0xE5,并同时修改FAT内容和位示图内容;如果文件不存在,给出出错信息 ⑻、文件拷贝 #CopyFile 老文件,新文件,为新文件创建一个目录项,并将老文件内容复制到新文件中,并同时修改FAT内容和位示图内容 ⑼、显示位示图内容 #ShowBitMP,将位示图内容(已有信息部分),显示在屏幕上(按十六进制)⑽、显示FAT内容 #ShowFAT,将FAT内容(已有信息部分),显示在屏幕上(按十六进制) 4、程序的总体流程为: ⑴、输出提示符#,等待接受命令,分析键入的命令; ⑵、对合法的命令,执行相应的处理程序,否则输出错误信息,继续等待新命令 关于对FAT表和MAP表的用法 1.当要用到数据块是,查询MAP表(因为只做比较查询即可),查询到的未用位置 置1,然后在FAT表上进行相应记录,在本程序做出的规定是,当文件夹FAT 表做-1,若是文件则按照FAT做对应的顺序记录,最后一块同样是-1结束,2.回收的时候,是按照FAT表的首项,做顺序置0,然后MAP也在相应位置置0 实时操作系统课程实验报告 专业:通信1001 学号:3100601025 姓名:陈治州 完成时间:2013年6月11日 实验简易电饭煲的模拟 一.实验目的: 掌握在基于嵌入式实时操作系统μC/OS-II的应用中,基于多任务的模式的编程方法。锻炼综合应用多任务机制,任务间的通信机制,内存管理等的能力。 二.实验要求: 1.按“S”开机,系统进入待机状态,时间区域显示当前北京时间,默认模式“煮饭”; 2.按“C”选择模式,即在“煮饭”、“煮粥”和“煮面”模式中循环选择; 3.按“B”开始执行模式命令,“开始”状态选中,时间区域开始倒计时,倒计时完成后进入“保温”状态,同时该状态显示选中,时间区域显示保温时间; 4.按“Q”取消当前工作状态,系统进入待机状态,时间区域显示北京时间,模式为当前模式; 5.按“X”退出系统,时间区域不显示。 6.煮饭时长为30,煮粥时长为50,煮面时长为40. 三.实验设计: 1.设计思路: 以老师所给的五个程序为基础,看懂每个实验之后,对borlandc的操作有了大概的认识,重点以第五个实验Task_EX为框架,利用其中界面显示与按键扫描以及做出相应的响应,对应实现此次实验所需要的功能。 本次实验分为界面显示、按键查询与响应、切换功能、时钟显示与倒计时模块,综合在一起实验所需功能。 2.模块划分图: (1)界面显示: Main() Taskstart() Taskstartdispinit() 在TaskStartDispInit()函数中,使用PC_DispStr()函数画出界面。 (2)按键查询与响应: Main() Taskstart() 在TaskStart()函数中,用if (PC_GetKey(&key) == TRUE)判断是否有按键输入。然后根据key 的值,判断输入的按键是哪一个;在响应中用switch语句来执行对应按键的响应。 (3)切换功能: l计数“C”按 键的次数 M=l%3 Switch(m) M=0,1,2对应于煮饭,煮粥,煮面,然后使用PC_DispStr()函数在选择的选项前画上“@”指示,同时,在其余两项钱画上“”以“擦出”之前画下的“@”,注意l自增。 四.主要代码: #include "stdio.h" #include "includes.h" #include "time.h" #include "dos.h" #include "sys/types.h" #include "stdlib.h" #define TASK_STK_SIZE 512 #define N_TASKS 2 OS_STK TaskStk[N_TASKS][TASK_STK_SIZE]; OS_STK TaskStartStk[TASK_STK_SIZE]; INT8U TaskData[N_TASKS]; 《操作系统》实验报告 实验序号: 4 实验项目名称:进程控制 Printf(“child Complete”); CloseHandle(pi.hProcess); CloseHandle(pi hThread); ﹜ 修改后: #include 实验任务:写出程序的运行结果。 4.正在运行的进程 (2)、编程二下面给出了一个使用进程和操作系统版本信息应用程序(文件名为4-5.cpp)。它利用进程信息查询的API函数GetProcessVersion()与GetVersionEx()的共同作用。确定运行进程的操作系统版本号。阅读该程序并完成实验任务。 #include 操作系统实验报告 集团企业公司编码:(LL3698-KKI1269-TM2483-LUI12689-ITT289- 实验二进程调度1.目的和要求 通过这次实验,理解进程调度的过程,进一步掌握进程状态的转变、进程调度的策略,进一步体会多道程序并发执行的特点,并分析具体的调度算法的特点,掌握对系统性能的评价方法。 2.实验内容 阅读教材《计算机操作系统》第二章和第三章,掌握进程管理及调度相关概念和原理。 编写程序模拟实现进程的轮转法调度过程,模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。假设初始状态为:有n个进程处于就绪状态,有m个进程处于阻塞状态。采用轮转法进程调度算法进行调度(调度过程中,假设处于执行状态的进程不会阻塞),且每过t个时间片系统释放资源,唤醒处于阻塞队列队首的进程。 程序要求如下: 1)输出系统中进程的调度次序; 2)计算CPU利用率。 3.实验环境 Windows操作系统、VC++6.0 C语言 4设计思想: (1)程序中进程可用PCB表示,其类型描述如下: structPCB_type { intpid;//进程名 intstate;//进程状态 2——表示“执行”状态 1——表示“就绪”状态 0——表示“阻塞”状态 intcpu_time;//运行需要的CPU时间(需运行的时间片个数) } 用PCB来模拟进程; (2)设置两个队列,将处于“就绪”状态的进程PCB挂在队列ready中;将处于“阻塞”状态的进程PCB挂在队列blocked中。队列类型描述如下: structQueueNode{ structPCB_typePCB; StructQueueNode*next; } 并设全程量: structQueueNode*ready_head=NULL,//ready队列队首指针 *ready_tail=NULL,//ready队列队尾指 针 实验二文件系统实验报告 一.实验简介 本实验要求在假设的I/O 系统之上开发一个简单的文件系统,这样做既能让实验者对文件系统有整体了解,又避免了涉及过多细节。用户通过create, open, read 等命令与文件系统交互。文件系统把磁盘视为顺序编号的逻辑块序列,逻辑块的编号为0 至L-1。I/O 系统利用内存中的数组模拟磁盘。 实际物理磁盘的结构是多维的:有柱面、磁道、扇区等概念。I/O 系统的任务是隐藏磁盘的结构细节,把磁盘以逻辑块的面目呈现给文件系统。逻辑块顺序编号,编号取值范围为0 至L .. 1,其中L 表示磁盘的存储块总数。实验中,我们可以利用字符数组ldisk[L][B] 构建磁盘模型,其中 B 表示每个存储块的长度。I/O 系统从文件系统接收命令,根据命令指定的逻辑块号把磁盘块的内容读入命令指定的内存区域,或者把命令指定的内存区域内容写入磁盘块。 我设计的文件系统拥有三个用户。 二.具体说明 1.文件系统的组织:磁盘的前k 个块是保留区,其中包含如下信息:位图和文件描述符。位图用来描述磁盘块的分配情况。位图中的每一位对应一个逻辑块。创建或者删除文件,以及文件的长度发生变化时,文件系统都需要进行位图操作。前k 个块的剩余部分包含一组文件描述符。每个文件描述符包含如下信息: ?文件长度,单位字节 ?文件分配到的磁盘块号数组。该数组的长度是一个系统参数。在实验中我们可以把它设置为一个比较小的数,例如3。 2.目录:我们的文件系统中仅设置一个目录,该目录包含文件系统中的所有文件。除了不需要显示地创建和删除之外,目录在很多方面和普通文件相像。目录对应0 号文件描述符。初始状态下,目录中没有文件,所有,目录对应的描述符中记录的长度应为0,而且也没有分配磁盘块。每创建一个文件,目录文件的长度便增加一分。目录文件的内容由一系列的目录项组成,其中每个目录项由如下内容组成: ?文件名 ?文件描述符序号 3.对文件的操作: 文件系统需提供如下函数;create, destroy, open, read, write。 ?create(filename): 根据指定的文件名创建新文件。 ?destroy(filename): 删除指定文件。 ?open(filename): 打开文件。该函数返回的索引号可用于后续的read, write, lseek, 或close 操作。 ?close(index): 关闭制定文件。 ?read(index, mem_area, count): 从指定文件顺序读入count 个字节mem_area 指定的内存位 操作系统教程 实 验 指 导 书 姓名: 学号: 班级:软124班 指导老师:郭玉华 2014年12月10日 实验一WINDOWS进程初识 1、实验目的 (1)学会使用VC编写基本的Win32 Consol Application(控制台应用程序)。 (2)掌握WINDOWS API的使用方法。 (3)编写测试程序,理解用户态运行和核心态运行。 2、实验内容和步骤 (1)编写基本的Win32 Consol Application 步骤1:登录进入Windows,启动VC++ 6.0。 步骤2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 Consol Application”,然后在“Project name”处输入工程名,在“Location”处输入工程目录。创建一个新的控制台应用程序工程。 步骤3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”, 然后在“File”处输入C/C++源程序的文件名。 步骤4:将清单1-1所示的程序清单复制到新创建的C/C++源程序中。编译成可执行文件。 步骤5:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入Windows“命令提示符”窗口,然后进入工程目录中的debug子目录,执行编译好的可执行程序: E:\课程\os课\os实验\程序\os11\debug>hello.exe 运行结果 (如果运行不成功,则可能的原因是什么?) : 有可能是因为DOS下路径的问题 (2)计算进程在核心态运行和用户态运行的时间 步骤1:按照(1)中的步骤创建一个新的“Win32 Consol Application”工程,然后将清单1-2中的程序拷贝过来,编译成可执行文件。 步骤2:在创建一个新的“Win32 Consol Application”工程,程序的参考程序如清单1-3所示,编译成可执行文件并执行。 步骤3:在“命令提示符”窗口中运行步骤1中生成的可执行文件,测试步骤2中可执行文件在核心态运行和用户态运行的时间。 E:\课程\os课\os实验\程序\os12\debug>time TEST.exe 步骤4:运行结果 (如果运行不成功,则可能的原因是什么?) : 因为程序是个死循环程序 步骤5:分别屏蔽While循环中的两个for循环,或调整两个for循环的次数,写出运行结果。 屏蔽i循环: 屏蔽j循环: _______________________________________________________________________________调整循环变量i的循环次数: 实验四文件系统实验 一 . 目的要求 1、用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。 2、要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。 二 . 例题: 1、设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。 2、程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)。 3、为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。 4、算法与框图: ①因系统小,文件目录的检索使用了简单的线性搜索。 ②文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。 ③程序中使用的主要设计结构如下: 主文件目录和用户文件目录( MFD、UFD) 打开文件目录( AFD)(即运行文件目录) 文件系统算法的流程图如下: 三 . 实验题: 1、增加 2~3个文件操作命令,并加以实现。(如移动读写指针,改变文件属性,更换文件名,改变文件保护级别)。 #include 嵌入式实时操作系统实验报告 任务间通信机制的建立 系别计算机与电子系 专业班级***** 学生姓名****** 指导教师 ****** 提交日期 2012 年 4 月 1 日 一、实验目的 掌握在基于嵌入式实时操作系统μC/OS-II的应用中,任务使用信号量的一般原理。掌握在基于优先级的可抢占嵌入式实时操作系统的应用中,出现优先级反转现象的原理及解决优先级反转的策略——优先级继承的原理。 二、实验内容 1.建立并熟悉Borland C 编译及调试环境。 2.使用课本配套光盘中第五章的例程运行(例5-4,例5-5,例5-6),观察运行结果,掌握信号量的基本原理及使用方法,理解出现优先级反转现象的根本原因并提出解决方案。 3.试编写一个应用程序,采用计数器型信号量(初值为2),有3个用户任务需要此信号量,它们轮流使用此信号量,在同一时刻只有两个任务能使用信号量,当其中一个任务获得信号量时向屏幕打印“TASK N get the signal”。观察程序运行结果并记录。 4. 试编写一个应用程序实现例5-7的内容,即用优先级继承的方法解决优先级反转的问题,观察程序运行结果并记录。 5.在例5-8基础上修改程序增加一个任务HerTask,它和YouTask一样从邮箱Str_Box里取消息并打印出来,打印信息中增加任务标识,即由哪个任务打印的;MyTask发送消息改为当Times为5的倍数时才发送,HerTask接收消息采用无等待方式,如果邮箱为空,则输出“The mailbox is empty”, 观察程序运行结果并记录。 三、实验原理 1. 信号量 μC/OS-II中的信号量由两部分组成:一个是信号量的计数值,它是一个16位的无符号整数(0 到65,535之间);另一个是由等待该信号量的任务组成的等待任务表。用户要在OS_CFG.H中将OS_SEM_EN开关量常数置成1,这样μC/OS-II 才能支持信号量。 实验(一) Windows 7基本操作 一、实验目的 1.掌握文件和文件夹基本操作。 2.掌握“资源管理器”和“计算机”基本操作。 二、实验要求 1.请将操作结果用Alt+Print Screen组合键截图粘贴在题目之后。 2.实验完成后,请将实验报告保存并提交。 三、实验内容 1.文件或文件夹的管理(提示:此题自行操作一遍即可,无需抓图)★期末机试必考题★ (1) 在D:盘根目录上创建一个名为“上机实验”的文件夹,在“上机实验”文件夹中创建1个名为“操作系统上机实验”的空白文件夹和2个分别名为“2.xlsx”和“3.pptx”的空白文件,在“操作系统上机实验”文件夹中创建一个名为“1.docx”的空白文件。 (2) 将“1.docx”改名为“介绍信.docx”;将“上机实验”改名为“作业”。 (3) 在“作业”文件夹中分别尝试选择一个文件、同时选择两个文件、一次同时选择所有文件和文件夹。 (4) 将“介绍信.docx”复制到C:盘根目录。 (5) 将D:盘根目录中的“作业”文件夹移动到C:盘根目录。 (6) 将“作业”文件夹中的“2.xlsx”文件删除放入“回收站”。 (7) 还原被删除的“2.xlsx”文件到原位置。 2.搜索文件或文件夹,要求如下: 查找C盘上所有以大写字母“A”开头,文件大小在10KB以上的文本文件。(提示:搜索时,可以使用“?”和“*”。“?”表示任意一个字符,“*”表示任意多个字符。) 3. 在桌面上为C:盘根目录下的“作业”文件夹创建一个桌面快捷方式。★期末机试必考题★ 3.“计算机”或“资源管理器”的使用 (1) 在“资源管理器”窗口,设置以详细信息方式显示C:\WINDOWS中所有文件和文件夹,使所有图标按类型排列显示,并不显示文件扩展名。(提示:三步操作全部做完后,将窗口中显示的最终设置结果抓一张图片即可) (2) 将C:盘根目录中“介绍信.docx”的文件属性设置为“只读”和“隐藏”,并设置在窗口中显示“隐藏属性”的文件或文件夹。(提示:请将“文件夹”对话框中选项设置效果与C:盘根目录中该文件图标呈现的半透明显示效果截取在一整张桌面图片中即可) 4.回收站的设置 设置删除文件后,不将其移入回收站中,而是直接彻底删除功能。 《操作系统原理》实验报告 实验项目名称:模拟使用银行家算法判断系统的状态 一、实验目的 银行家算法是操作系统中避免死锁的算法,本实验通过对银行家算法的模拟,加强对操作系统中死锁的认识,以及如何寻找到一个安全序列解除死锁。 二、实验环境 1、硬件:笔记本。 2、软件:Windows 7 , Eclipse。 三、实验内容 1.把输入资源初始化,形成资源分配表; 2.设计银行家算法,输入一个进程的资源请求,按银行家算法步骤进行检查; 3.设计安全性算法,检查某时刻系统是否安全; 4.设计显示函数,显示资源分配表,安全分配序列。 四、数据处理与实验结果 1.资源分配表由进程数组,Max,Allocation,Need,Available 5个数组组成; 实验采用数据为下表: 2.系统总体结构,即菜单选项,如下图 实验的流程图。如下图 3.实验过程及结果如下图所示 1.首先输入进程数和资源类型及各进程的最大需求量 2.输入各进程的占有量及目前系统的可用资源数量 3.初始化后,系统资源的需求和分配表 4.判断线程是否安全 5.对线程进行死锁判断 五、实验过程分析 在实验过程中,遇到了不少问题,比如算法无法回滚操作,程序一旦执行,必须直接运行到单个任务结束为止,即使产生了错误,也必须等到该项任务结束才可以去选择别的操作。但总之,实验还是完满的完成了。 六、实验总结 通过实验使我对以前所学过的基础知识加以巩固,也对操作系统中抽象理论知识加以理解,例如使用Java语言来实现银行家算法,在这个过程中更进一步了解了银行家算法,通过清晰字符界面能进行操作。不过不足之处就是界面略显简洁,对于一个没有操作过计算机的人来说,用起来可能还是有些难懂。所以,以后会对界面以及功能进行完善,做到人人都可以看懂的算法。 实验报告 实验课程名称:操作系统 实验地点:南主楼七楼机房 2018—2019学年(一)学期 2018年 9月至 2019 年 1 月 专业: 班级: 学号: 姓名: 指导老师:刘一男 实验一 实验项目:分时系统模拟 实验学时:2实验日期: 2018-10-25 成绩: 实验目的利用程序设计语言模拟分时系统中多个进程按时间片轮转调度算法进行进程调度的过程; 假设有五个进程A,B,C,D,E,它们的到达时间及要求服务的时间分别为:进程名 A B C D E 到达时间0 1 2 3 4 服务时间 4 3 4 2 4 时间片大小为1,利用程序模拟A,B,C,D,E五个进程按时间片轮转的调度及执行过程并计算各进程的周转时间及带权周转时间。 执行过程并计算各进程的周转时间及带权周转时间。 轮转调度:BDACE (1)修改时间片大小为2,利用程序模拟A,B,C,D,E五个进程按时间片轮转的调度及执行过程并计算各进程的周转时间及带权周转时间。 轮转调度:ADBCE (2)修改时间片大小为4,利用程序模拟A,B,C,D,E五个进程按时间片轮转的调度及执行过程并计算各进程的周转时间及带权周转时间. 顺序:ABCDE 1、思考 时间片的大小对调度算法产生什么影响?对计算机的性能产生什么影响?答:通过对时间片轮转调度算法中进程最后一次执行时间片分配的优化,提出了一种改进的时间片轮转调度算法,该算法具有更好的实时性,同时减少了任务调度次数和进程切换次数,降低了系统开销,提升了CPU的运行效率,使操作系统的性能得到了一定的提高。 A B C D E 时间片为1 周转时间12 9 14 8 13 3 3 3.5 4 3.25 带权周转 时间 时间片为2 周转时间8 12 13 7 13 2 4 3.25 3.5 3.25 带权周转 时间 时间片为4 周转时间 4 6 9 10 13 1 2 2.25 5 3.25 带权周转 时间文件系统实验报告
操作系统实验报告--实验一--进程管理
山东大学操作系统实验报告4进程同步实验
操作系统实验报告
Linux文件系统实验报告
嵌入式操作系统实验报告
FAT文件系统操作系统课程设计实验报告
实时操作系统报告
操作系统实验报告4
操作系统实验报告
文件系统实验报告
操作系统实验报告
实验四 文件系统实验报告
嵌入式实时操作系统实验报告
《 Windows7 操作系统》实验报告
操作系统实验报告
操作系统实验报告