操作系统实验报告实验一:用户接口实验一.实验目的1.理解面向操作命令的接口Shell。
2.学会简单的shell编码。
3.理解操作系统调用的运行机制。
4.掌握创建系统调用的方法。
操作系统给用户提供了命令接口和程序接口(系统调用)两种操作方式。
用户接口实验也因此而分为两大部分。
首先要熟悉Linux的基本操作命令,并在此基础上学会简单的shell编程方法。
然后通过想Linux内核添加一个自己设计的系统调用,来理解系统调用的实现方法和运行机制。
在本次实验中,最具有吸引力的地方是:通过内核编译,将一组源代码变成操作系统的内核,并由此重新引导系统,这对我们初步了解操作系统的生成过程极为有利。
二.实验内容1)控制台命令接口实验该实验是通过“几种操作系统的控制台命令”、“终端处理程序”、“命令解释程序”和“Linux操作系统的bash”来让实验者理解面向操作命令的接口shell 和进行简单的shell编程。
➢查看bash版本。
➢编写bash脚本,统计/my目录下c语言文件的个数2)系统调用实验该实验是通过实验者对“Linux操作系统的系统调用机制”的进一步了解来理解操作系统调用的运行机制;同时通过“自己创建一个系统调用mycall()”和“编程调用自己创建的系统调用”进一步掌握创建和调用系统调用的方法。
➢编程调用一个系统调用fork(),观察结果。
➢编程调用创建的系统调用foo(),观察结果。
➢自己创建一个系统调用mycall(),实现功能:显示字符串到屏幕上。
➢编程调用自己创建的系统调用。
三.实验步骤系统调用实验:1.首先将Linux-3.0.tar.bz2拷贝到/usr/src目录下——命令:cp linux-3.0.tar.bz2 /usr/src/2.打开终端,获得root权限——命令:sudo –s3.进入/usr/src目录——命令:cd /usr/src4.解压linux源码——命令:tar xvzf linux-3.0.tar.bz25.进入目录linux-3.0.5——命令:cd linux-3.06.添加系统调用——操作:gedit kernel/myservice.c 在文本编辑器中添加#include <linux/kernel.h>#include <linux/linkage.h>asmlinkage void sys_mycall(){printk(KERN_INFO "Hello, world!\n");return;}7.修改kernel/Makefile添加生成myservice.c添加到Makefile的编译规则中:obj-y += myservice.o8..修改arch/x86/include/asm/unistd_32.h,添加以下内容:#define __NR_mycall SYS_ID//SYS_ID表示新添加系统调用的调用号并修改文件中的NR_syscalls,将其值增加19.修改arxh/x86/include/asm/syscalls.h添加以下内容:asmlinkage void sys_mycall();10.修改arch/x86/kernel/syscall_table_32.S,添加以下内容:.long sys_mycall11.配置内核(仅仅修改local versions即可)——命令:make menuconfig12.编译内核——命令:make –j4 bzImage(开4个线程编译)13.编译内核模块——命令:make –j4 modules14.安装内核模块——命令:make modules_install15.安装内核——命令:make install16.重启系统,在系统选择页面选择进入自己编译的linux-3.0内核17.在桌面建立测试的C程序test.c程序内容如下:#include <stdio.h>int main(int argc, char *argv[]){syscall(SYS_ID); // SYS_ID表示新添加系统调用的调用号return 0;}18.编译程序——gcc test.c –o a.out19.运行程序——./a.out20.查看内核日志(printk的输出信息在内核日志中):dmesg四.实验结果1.成功完成内核编译的任务,结果显示图如下:2.下图为添加系统调用结果五.实验小结这次实验的内核编译需要进行一系列比较花时间的操作过程,但同时也锻炼了实际动手能力,在实践中对于操作系统这门课有了进一步的了解。
同时,在本次实验中,学习了linux系统的使用方法,掌握了很多的基本命令,也明白了添加系统调用的方法,为以后的学习提供了很大的帮助。
实验四:一个简单文件系统的实现一.实验目的1.熟悉Ext文件系统的原理2.根据Ext文件系统的数据结构和构建方法,自行实现一个简单的内存文件系统二.实验内容1.设计并实现一个一级(单用户)文件系统程序a.提供以下操作:a)文件创建/删除接口命令create/deleteb)目录创建/删除接口命令mkdir/rmdirc)显示目录内容命令lsb.创建的文件不要求格式和内容2.设计并实现一个二级文件系统程序a.提供用户登录;b.文件、目录要有权限三.实验原理1.Ext文件系统结构:2.3.引导块BootBlock每个硬盘分区的开头1024字节,即0 byte至1023 byte是分区的启动扇区。
存放由ROM BIOS自动读入的引导程序和数据,但这只对引导设备有效,而对于非引导设备,该引导块不含代码。
这个块与ext2没有任何关系。
4.超级块SuperBlock每个分区均有一个super block块,定义了文件系统的全局信息,包括块的大小,总块数,空闲块,索引结点数,各种位图和i节点表的地址和大小等信息。
5.数据块位图这是ext2管理存储空间的方法。
即位图法。
每个位对应一个数据块,位值为0表示空闲,1表示已经分配。
数据块位图定义为一个块大小。
于是,一个组中的数据块个数就决定了。
假设块大小为b 字节。
可以区别的块数为b*8个6.数据块DataBlocks每个组的数据最大个数是在块大小定义后就确定了的。
所以组容量也就确定了。
假设块大小为b 字节。
那么组容量就确定为(b*8)*b字节若1块=4K,则组块大小=4K*8*4K=128M7.inode位图与数据块位图相似,用来表示索引结点是否已经被使用。
假设块大小为b 字节,每个索引结点数据结构大小为128字节。
最多可以有b*8个索引结点,索引结点表需要占用的存储空间大小为(b*8)*128字节。
即(b*8)*128/b=8*128个块8.inode表索引结点表由若干个索引结点数据结构组成,需要占用若干个块。
Ext2中的每个索引结点数据结构大小为128字节。
每个索引结点即对应一个文件或是目录。
是对其除文件名(目录名)以外的所有属性的描述。
例如:文件类型,文件创建时间,访问时间,修改时间,文件所占数据块的个数,指向数据块的指针。
其中,数据块指针是由15个元组的数据组成四.实验步骤运行结果1.根据要求编写源程序,实验源代码见附录1。
2. 运行程序,运行结果如图:1.根据提示输入help,结果如图:2.输入ls 列出根目录下的项目,然后创建文件目录c 再输入ls观察是否创建成功:5.进入文件目录c并在c中创建文件a6.打开a,并读取a7. 关闭a 9.删除a9. 删除文件目录c五.实验小结本次实验要求建立一个文件系统,由于在专业课上的基本知识学习比较薄弱,所以参考了网上的一些代码,进行了一些修改后最后获得结果。
最后,也算完成了一个简单的文件系统,具备了题目中的要求。
但在以后的学习中,还要对这一方面的知识进行一些补充。
附录1:实验源码:#include <stdio.h>#include <time.h>#include <string.h>#include <signal.h>#define DATA_BLOCK 263680 //数据块起始地址#define BLOCK_SIZE 512 //块大小#define DISK_START 0 //磁盘开始地址#define BLOCK_BITMAP 512 //块位图起始地址#define INODE_BITMAP 1024//inode 位图起始地址#define INODE_TABLE 1536//索引节点表起始地址#define INODE_SIZE 64 //struct inode的大小struct group_desc{char bg_volume_name[16]; //卷名unsigned short bg_block_bitmap; //保存块位图的块号unsigned short bg_inode_bitmap; //保存索引结点位图的块号unsigned short bg_inode_table; //索引结点表的起始块号unsigned short bg_free_blocks_count; //本组空闲块的个数unsigned short bg_free_inodes_count; //本组空闲索引结点的个数unsigned short bg_used_dirs_count; //本组目录的个数char bg_pad[4]; //填充(0xff)};struct inode{unsigned short i_mode; //文件类型及访问权限unsigned short i_blocks; //文件的数据块个数unsigned long i_size; //大小( 字节)unsigned long i_atime; //访问时间unsigned long i_ctime; //创建时间unsigned long i_mtime; //修改时间unsigned long i_dtime; //删除时间unsigned short i_block[8]; //指向数据块的指针char i_pad[24]; //填充(0xff)};struct dir_entry{ //目录项结构unsigned short inode; //索引节点号unsigned short rec_len; //目录项长度unsigned short name_len; //文件名长度char file_type; //文件类型(1: 普通文件,2: 目录.. )char name[9]; //文件名};char Buffer[512]; //针对数据块的缓冲区char tempbuf[4097]; //unsigned char bitbuf[512]; //位图缓冲区unsigned short index_buf[256];short fopen_table[16]; // 文件打开表unsigned short last_alloc_inode; // 最近分配的节点号unsigned short last_alloc_block; // 最近分配的数据块号unsigned short current_dir; // 当前目录的节点号struct group_desc super_block[1]; // 组描述符缓冲区struct inode inode_area[1]; // 节点缓冲区struct dir_entry dir[32]; // 目录项缓冲区char current_path[256]; // 当前路径名unsigned short current_dirlen;FILE *fp;void update_group_desc(){fseek(fp,DISK_START,SEEK_SET);fwrite(super_block,BLOCK_SIZE,1,fp);}void reload_group_desc()//载入组描述符{fseek(fp,DISK_START,SEEK_SET);fread(super_block,BLOCK_SIZE,1,fp);}void update_inode_bitmap()//更新inode位图{fseek(fp,INODE_BITMAP,SEEK_SET);fwrite(bitbuf,BLOCK_SIZE,1,fp);}void reload_inode_bitmap()//载入inode位图{fseek(fp,INODE_BITMAP,SEEK_SET);fread(bitbuf,BLOCK_SIZE,1,fp);}void update_block_bitmap()//更新block位图{fseek(fp,BLOCK_BITMAP,SEEK_SET);fwrite(bitbuf,BLOCK_SIZE,1,fp);}void reload_block_bitmap()//载入block位图{fseek(fp,BLOCK_BITMAP,SEEK_SET);fread(bitbuf,BLOCK_SIZE,1,fp);}void update_inode_entry(unsigned short i)//更新第i个inode入口{fseek(fp,INODE_TABLE+(i-1)*INODE_SIZE,SEEK_SET);fwrite(inode_area,INODE_SIZE,1,fp);}void reload_inode_entry(unsigned short i)//载入第i个inode入口{fseek(fp,INODE_TABLE+(i-1)*INODE_SIZE,SEEK_SET);fread(inode_area,INODE_SIZE,1,fp);}void reload_dir(unsigned short i)//更新第i个目录{fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);fread(dir,BLOCK_SIZE,1,fp);}void update_dir(unsigned short i)//载入第i个目录{fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);fwrite(dir,BLOCK_SIZE,1,fp);}void reload_block(unsigned short i)//载入第i个数据块{fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);fread(Buffer,BLOCK_SIZE,1,fp);}void update_block(unsigned short i)//更新第i个数据块{fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);fwrite(Buffer,BLOCK_SIZE,1,fp);}int alloc_block()//分配一个数据块,返回数据块号;{unsigned short cur=last_alloc_block;unsigned char con=128;int flag=0;if(super_block[0].bg_free_blocks_count==0){printf("There is no block to be alloced!\n");return(0);}reload_block_bitmap();cur=cur/8;while(bitbuf[cur]==255){if(cur==511)cur=0;else cur++;}while(bitbuf[cur]&con){con=con/2;flag++;}bitbuf[cur]=bitbuf[cur]+con;last_alloc_block=cur*8+flag;update_block_bitmap();super_block[0].bg_free_blocks_count--;update_group_desc();return last_alloc_block;}void remove_block(unsigned short del_num)//删除一个block {unsigned short tmp;tmp=del_num/8;reload_block_bitmap();switch(del_num%8)//更改block位图{case 0:bitbuf[tmp]=bitbuf[tmp]&127;break;case 1:bitbuf[tmp]=bitbuf[tmp]&191;break;case 2:bitbuf[tmp]=bitbuf[tmp]&223;break;case 3:bitbuf[tmp]=bitbuf[tmp]&239;break;case 4:bitbuf[tmp]=bitbuf[tmp]&247;break;case 5:bitbuf[tmp]=bitbuf[tmp]&251;break;case 6:bitbuf[tmp]=bitbuf[tmp]&253;break;case 7:bitbuf[tmp]=bitbuf[tmp]&254;break;}update_block_bitmap();super_block[0].bg_free_blocks_count++;update_group_desc();}//int get_inode()//分配一个inode,返回序号{unsigned short cur=last_alloc_inode;unsigned char con=128;int flag=0;if(super_block[0].bg_free_inodes_count==0){printf("There is no Inode to be alloced!\n");return 0;}reload_inode_bitmap();cur=(cur-1)/8;while(bitbuf[cur]==255){if(cur==511)cur=0;else cur++;}while(bitbuf[cur]&con){con=con/2;flag++;}bitbuf[cur]=bitbuf[cur]+con;last_alloc_inode=cur*8+flag+1;update_inode_bitmap();super_block[0].bg_free_inodes_count--;update_group_desc();return last_alloc_inode;}//void remove_inode(unsigned short del_num){unsigned short tmp;tmp=(del_num-1)/8;reload_inode_bitmap();switch((del_num-1)%8)//更改block位图{case 0:bitbuf[tmp]=bitbuf[tmp]&127;break;case 1:bitbuf[tmp]=bitbuf[tmp]&191;break;case 2:bitbuf[tmp]=bitbuf[tmp]&223;break;case 3:bitbuf[tmp]=bitbuf[tmp]&239;break;case 4:bitbuf[tmp]=bitbuf[tmp]&247;break;case 5:bitbuf[tmp]=bitbuf[tmp]&251;break;case 6:bitbuf[tmp]=bitbuf[tmp]&253;break;case 7:bitbuf[tmp]=bitbuf[tmp]&254;break;}update_inode_bitmap();super_block[0].bg_free_inodes_count++;update_group_desc();}// dirvoid dir_prepare(unsigned short tmp,unsigned short len,int type) //新目录和文件初始化.and ..{reload_inode_entry(tmp);//得到新目录的节点入口地址if(type==2)//目录{inode_area[0].i_size=32;inode_area[0].i_blocks=1;inode_area[0].i_block[0]=alloc_block();dir[0].inode=tmp;dir[1].inode=current_dir;dir[0].name_len=len;dir[1].name_len=current_dirlen;dir[0].file_type=dir[1].file_type=2;for(type=2;type<32;type++)dir[type].inode=0;strcpy(dir[0].name,".");strcpy(dir[1].name,"..");update_dir(inode_area[0].i_block[0]);inode_area[0].i_mode=01006;//drwxrwxrwx:目录}else{inode_area[0].i_size=0;inode_area[0].i_blocks=0;inode_area[0].i_mode=0407;//drwxrwxrwx:文件}update_inode_entry(tmp);}//unsigned short reserch_file(char tmp[9],int file_type,unsigned short *inode_num,unsigned short *block_num,unsigned short *dir_num){ //查找文件并改写缓冲区里节点号,所在目录节点的数据块号(0~7)、目录项所在号unsigned short j,k;reload_inode_entry(current_dir);j=0;while(j<inode_area[0].i_blocks){reload_dir(inode_area[0].i_block[j]);k=0;while(k<32){if(!dir[k].inode||dir[k].file_type!=file_type||strcmp(dir[k].name,tmp))k++;else{*inode_num=dir[k].inode;*block_num=j;*dir_num=k;return 1;}}j++;}return 0;}//void cd(char tmp[9]){unsigned short i,j,k,flag;flag=reserch_file(tmp,2,&i,&j,&k);if(flag){current_dir=i;if(!strcmp(tmp,"..")&&dir[k-1].name_len){current_path[strlen(current_path)-dir[k-1].name_len-1]='\0';current_dirlen=dir[k].name_len;}else if(!strcmp(tmp,"."));else if(strcmp(tmp,"..")){current_dirlen=strlen(tmp);strcat(current_path,tmp);strcat(current_path,"/");}}else printf("The directory %s not exists!\n",tmp);}//void del(char tmp[9])unsigned short i,j,k,m,n,flag;m=0;flag=reserch_file(tmp,1,&i,&j,&k);if(flag){flag=0;while(fopen_table[flag]!=dir[k].inode&&flag<16)flag++;if(flag<16)fopen_table[flag]=0;reload_inode_entry(i);while(m<inode_area[0].i_blocks)remove_block(inode_area[0].i_block[m++]);inode_area[0].i_blocks=0;inode_area[0].i_size=0;remove_inode(i);reload_inode_entry(current_dir);dir[k].inode=0;//if(k!=0)dir[k-1].rec_len+=dir[k].rec_len ;update_dir(inode_area[0].i_block[j]);inode_area[0].i_size-=16;m=1;while(m<inode_area[i].i_blocks){flag=n=0;reload_dir(inode_area[0].i_block[m]);while(n<32){if(!dir[n].inode)flag++;n++;}if(flag==32){remove_block(inode_area[i].i_block[m]);inode_area[i].i_blocks--;while(m<inode_area[i].i_blocks)inode_area[i].i_block[m]=inode_area[i].i_block[++m];}}update_inode_entry(current_dir);}else printf("The file %s not exists!\n",tmp);}//void mkdir(char tmp[9],int type)unsigned short tmpno,i,j,k,flag;reload_inode_entry(current_dir); //获得当前目录的索引节点给inode_area[0]if(!reserch_file(tmp,type,&i,&j,&k)) //未找到同名文件{if(inode_area[0].i_size==4096) //目录项已满{printf("Directory has no room to be alloced!\n");return;}flag=1;if(inode_area[0].i_size!=inode_area[0].i_blocks*512)//目录中有某些个块中32个项未满{i=0;while(flag&&i<inode_area[0].i_blocks){reload_dir(inode_area[0].i_block[i]);j=0;while(j<32){if(dir[j].inode==0){flag=0;break;}j++;}i++;}tmpno=dir[j].inode=get_inode();dir[j].name_len=strlen(tmp);dir[j].file_type=type;strcpy(dir[j].name,tmp);update_dir(inode_area[0].i_block[i-1]);}else//全满{inode_area[0].i_block[inode_area[0].i_blocks]=alloc_block();inode_area[0].i_blocks++;reload_dir(inode_area[0].i_block[inode_area[0].i_blocks-1]);tmpno=dir[0].inode=get_inode();dir[0].name_len=strlen(tmp);dir[0].file_type=type;strcpy(dir[0].name,tmp);//初始化新块for(flag=1;flag<32;flag++)dir[flag].inode=0;update_dir(inode_area[0].i_block[inode_area[0].i_blocks-1]);}inode_area[0].i_size+=16;update_inode_entry(current_dir);dir_prepare(tmpno,strlen(tmp),type);}else //已经存在同名文件或目录{if(type==1)printf("File has already existed!\n");else printf("Directory has already existed!\n");}}//void rmdir(char tmp[9]){unsigned short i,j,k,flag;unsigned short m,n;if(!strcmp(tmp,"..")||!strcmp(tmp,".")){printf("The directory can not be deleted!\n");return;}flag=reserch_file(tmp,2,&i,&j,&k);if(flag){reload_inode_entry(dir[k].inode); //找到要删除的目录的节点并载入if(inode_area[0].i_size==32) //只有.and ..{inode_area[0].i_size=0;inode_area[0].i_blocks=0;//reload_dir(inode_area[0].i_block[0]);//dir[0].inode=0;//dir[1].inode=0;remove_block(inode_area[0].i_block[0]);reload_inode_entry(current_dir);//得到当前目录的节点并更改当前目录项remove_inode(dir[k].inode);dir[k].inode=0;update_dir(inode_area[0].i_block[j]);inode_area[0].i_size-=16;flag=0;m=1;while(flag<32&&m<inode_area[0].i_blocks){flag=n=0;reload_dir(inode_area[0].i_block[m]);while(n<32){if(!dir[n].inode)flag++;n++;}if(flag==32){remove_block(inode_area[0].i_block[m]);inode_area[0].i_blocks--;while(m<inode_area[0].i_blocks)inode_area[0].i_block[m]=inode_area[0].i_block[++m];}}update_inode_entry(current_dir);}else printf("Directory is not null!\n");}else printf("Directory to be deleted not exists!\n");}//void ls(){int i,j,k,tmpno,no;i=0;printf("items type mode size\n");reload_inode_entry(current_dir);while(i<inode_area[0].i_blocks){k=0;reload_dir(inode_area[0].i_block[i]);while(k<32){if(dir[k].inode){printf("%s",dir[k].name);if(dir[k].file_type==2){j=0;reload_inode_entry(dir[k].inode);if(!strcmp(dir[k].name,".."))while(j++<13)printf(" ");else if(!strcmp(dir[k].name,"."))while(j++<14)printf(" ");else while(j++<15-dir[k].name_len)printf(" ");printf("<DIR> ");switch(inode_area[0].i_mode&7){case 1:printf("____x");break;case 2:printf("__w__");break;case 3:printf("__w_x");break;case 4:printf("r____");break;case 5:printf("r___x");break;case 6:printf("r_w__");break;case 7:printf("r_w_x");break;}printf(" ----");}else if(dir[k].file_type==1){j=0;reload_inode_entry(dir[k].inode);while(j++<15-dir[k].name_len)printf(" ");printf("<FILE> ");switch(inode_area[0].i_mode&7){case 1:printf("____x");break;case 2:printf("__w__");break;case 3:printf("__w_x");break;case 4:printf("r____");break;case 5:printf("r___x");break;case 6:printf("r_w__");break;case 7:printf("r_w_x");break;}printf(" %d bytes ",inode_area[0].i_size);}printf("\n");}k++;reload_inode_entry(current_dir);}i++;}}// fileunsigned short search_file(unsigned short Ino)//在打开文件表中查找是否已打开文件{unsigned short fopen_table_point=0;while(fopen_table_point<16&&fopen_table[fopen_table_point++]!=Ino);if(fopen_table_point==16)return 0;return 1;}//void read_file(char tmp[9])//读文件{unsigned short flag,i,j,k;flag=reserch_file(tmp,1,&i,&j,&k); //返回文件目录项的信息if(flag){if(search_file(dir[k].inode)){reload_inode_entry(dir[k].inode);if(!(inode_area[0].i_mode&4))//i_mode:111b:读,写,执行{printf("The file %s can not be read!\n",tmp);return;}for(flag=0;flag<inode_area[0].i_blocks;flag++){reload_block(inode_area[0].i_block[flag]);Buffer[512]='\0';printf("%s",Buffer);}if(flag==0)printf("The file %s is empty!\n",tmp);else printf("\n");}else printf("The file %s has not been opened!\n",tmp);}else printf("The file %s not exists!\n",tmp);}void write_file(char tmp[9])//写文件{unsigned short flag,i,j,k,size=0,need_blocks;flag=reserch_file(tmp,1,&i,&j,&k);if(flag){if(search_file(dir[k].inode)){reload_inode_entry(dir[k].inode);if(!(inode_area[0].i_mode&2))//i_mode:111b:读,写,执行{printf("The file %s can not be writed!\n",tmp);return;}while(1){tempbuf[size]=getchar();if(tempbuf[size]=='#'){tempbuf[size]='\0';break;}if(size>=4096){printf("Sorry,the max size of a file is 4KB!\n");tempbuf[size]='\0';break;}size++;}need_blocks=strlen(tempbuf)/512;if(strlen(tempbuf)%512)need_blocks++;if(need_blocks<9){while(inode_area[0].i_blocks<need_blocks){inode_area[0].i_block[inode_area[0].i_blocks]=alloc_block();inode_area[0].i_blocks++;}j=0;while(j<need_blocks){if(j!=need_blocks-1){reload_block(inode_area[0].i_block[j]);memcpy(Buffer,tempbuf+j*BLOCK_SIZE,BLOCK_SIZE);update_block(inode_area[0].i_block[j]);}else{reload_block(inode_area[0].i_block[j]);memcpy(Buffer,tempbuf+j*BLOCK_SIZE,strlen(tempbuf)-j*BLOCK_SIZE);if(strlen(tempbuf)>inode_area[0].i_size){Buffer[strlen(tempbuf)-j*BLOCK_SIZE]='\0';inode_area[0].i_size=strlen(tempbuf);}update_block(inode_area[0].i_block[j]);}j++;}update_inode_entry(dir[k].inode);}else printf("Sorry,the max size of a file is 4KB!\n");}else printf("The file %s has not opened!\n",tmp);}else printf("The file %s does not exist!\n",tmp);}//void close_file(char tmp[9])//关闭文件{unsigned short flag,i,j,k;flag=reserch_file(tmp,1,&i,&j,&k);if(flag){if(search_file(dir[k].inode)){flag=0;while(fopen_table[flag]!=dir[k].inode)flag++;fopen_table[flag]=0;printf("File: %s! closed\n",tmp);}else printf("The file %s has not been opened!\n",tmp);}else printf("The file %s does not exist!\n",tmp);}void open_file(char tmp[9]){unsigned short flag,i,j,k;flag=reserch_file(tmp,1,&i,&j,&k);if(flag){if(search_file(dir[k].inode))printf("The file %s has opened!\n",tmp);else{flag=0;while(fopen_table[flag])flag++;fopen_table[flag]=dir[k].inode;printf("File %s! opened\n",tmp);}}else printf("The file %s does not exist!\n",tmp);}// formatvoid initialize_disk(){int i=0;printf("Creating the ext2 file system\n");printf("Please wait ");while(i<1){printf("... ");// sleep(1);i++;}printf("\n");last_alloc_inode=1;last_alloc_block=0;for(i=0;i<16;i++)fopen_table[i]=0;//清空缓冲表for(i=0;i<BLOCK_SIZE;i++)Buffer[i]=0;// 清空缓冲区,通过缓冲区清空文件,即清空磁盘fp=fopen("FS_zqw_zzw.txt","w+b");fseek(fp,DISK_START,SEEK_SET);for(i=0;i<4611;i++)fwrite(Buffer,BLOCK_SIZE,1,fp);//清空文件,即清空磁盘全部用0填充reload_group_desc();reload_inode_entry(1);reload_dir(0);strcpy(current_path,"[root@ /"); //该路径名strcpy(super_block[0].bg_volume_name,"EXT2FS"); //改卷名,初始化组描述符内容super_block[0].bg_block_bitmap=BLOCK_BITMAP;super_block[0].bg_inode_bitmap=INODE_BITMAP;super_block[0].bg_inode_table=INODE_TABLE;super_block[0].bg_free_blocks_count=4096;super_block[0].bg_free_inodes_count=4096;super_block[0].bg_used_dirs_count=0;// 初始化组描述符内容update_group_desc(); //更新组描述符内容reload_block_bitmap();reload_inode_bitmap();inode_area[0].i_mode=518;inode_area[0].i_blocks=0;inode_area[0].i_size=32;inode_area[0].i_atime=0;inode_area[0].i_ctime=0;inode_area[0].i_mtime=0;inode_area[0].i_dtime=0;inode_area[0].i_block[0]=alloc_block();inode_area[0].i_blocks++;current_dir=get_inode();update_inode_entry(current_dir);dir[0].inode=dir[1].inode=current_dir;dir[0].name_len=0;dir[1].name_len=0;dir[0].file_type=dir[1].file_type=2;//1:文件;2:目录strcpy(dir[0].name,".");strcpy(dir[1].name,"..");update_dir(inode_area[0].i_block[0]);printf("The ext2 file system has been installed!\n");}void initialize_memory(){int i=0;last_alloc_inode=1;last_alloc_block=0;for(i=0;i<16;i++)fopen_table[i]=0;strcpy(current_path,"[root@ /");current_dir=1;fp=fopen("FS_zqw_zzw.txt","r+b");if(fp==NULL){printf("The File system does not exist!\n");initialize_disk();return ;}reload_group_desc();}void format(){initialize_disk();initialize_memory();}void help(){printf(" ext文件系统模拟\n");printf(" 可以使用的命令: \n");printf(" 1.进入文件目录: cd+dir_name 7.创建文件目录: mkdir+dir_name \n");printf(" 2.创建文件: mkf+file_name 8.删除目录: rmdir+dir_name \n");printf(" 3.删除文件: rm+file_name 9.读取文件: read+file_name \n");printf(" 4.打开文件: open+file_name 10.写文件: write+file_name \n");printf(" 5.关闭文件: close+file_name 11.退出: quit \n");printf(" 6.列出项目: ls 12.查看帮助: help \n");printf(" 13.format disk : format \n");}// mainint main(char argc,char **argv){char command[10],temp[9];initialize_memory();printf("输入help查看帮助\n");while(1){printf("%s]#",current_path);scanf("%s",command);if(!strcmp(command,"cd")){scanf("%s",temp);cd(temp);}else if(!strcmp(command,"mkdir")) {scanf("%s",temp);mkdir(temp,2);}else if(!strcmp(command,"mkf")) {scanf("%s",temp);mkdir(temp,1);}else if(!strcmp(command,"rmdir")) {scanf("%s",temp);rmdir(temp);}else if(!strcmp(command,"rm")) {scanf("%s",temp);del(temp);}else if(!strcmp(command,"open")) {scanf("%s",temp);open_file(temp);}else if(!strcmp(command,"close")) {scanf("%s",temp);close_file(temp);}else if(!strcmp(command,"read")) {scanf("%s",temp);read_file(temp);}else if(!strcmp(command,"write")) {scanf("%s",temp);write_file(temp);}else if(!strcmp(command,"ls"))ls();else if(!strcmp(command,"format")){char tempch;printf("Format will erase all the data in the Disk\n");printf("Are you sure?y/n:\n");scanf(" %c",&tempch);if(tempch=='Y'||tempch=='y'){fclose(fp);initialize_disk();}elseprintf("Format Disk canceled\n");}else if(!strcmp(command,"help"))help();else if(!strcmp(command,"quit"))break;else printf("No this Command,Please check!\n");}return 0;}。