文件管理系统模拟
1.实验目的
通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能及内部实现2.实验内容
为Linux系统设计一个简单的二级文件系统。要求做到以下几点:
(1)可以实现下列几条命令(至少4条)
login 用户登录
dir 列文件目录
create 创建文件
delete 删除文件
open 打开文件
close 关闭文件
read 读文件
write 写文件
(2)列目录时要列出文件名、物理地址、保护码和文件长度;
(3)源文件可以进行读写保护。
3.实验提示
(1)首先应确定文件系统的数据结构:主目录、子目录及活动文件等。主目录和子目录都以文件的形式存放于磁盘,这样便于查找和修改。
(2)用户创建的文件,可以编号存储于磁盘上。入file0,file1,file2…并以编号作为物理地址,在目录中进行登记。
4.源代码
#include
#include
#include
#define MEM_D_SIZE 1024*1024 //总磁盘空间为1M
#define DISKSIZE 1024 //磁盘块的大小1K
#define DISK_NUM 1024
//磁盘块数目1K
#define FATSIZE DISK_NUM*sizeof(struct fatitem) //FAT表大小
#define ROOT_DISK_NO FATSIZE/DISKSIZE+1
//根目录起始盘块号
#define ROOT_DISK_SIZE sizeof(struct direct) //根目录大小
#define DIR_MAXSIZE 1024
//路径最大长度为1KB
#define MSD 5
//最大子目录数5#define MOFN 5
//最大文件深度为5
#define MAX_WRITE 1024*128
//最大写入文字长度128KB struct fatitem /* size 8*/
{
int item; /*存放文件下一个磁盘的指针*/
char em_disk; /*磁盘块是否空闲标志位0 空闲*/
};
struct direct
{
/*-----文件控制快信息-----*/
struct FCB
{
char name[9]; /*文件/目录名8位*/
char property; /*属性1位目录0位普通文件*/
int size; /*文件/目录字节
数、盘块数)*/
int firstdisk; /*文件/目录起始盘块号*/
int next; /*子目录起始盘块号*/
int sign; /*1是根目录0不是根目录*/
}directitem[MSD+2];
};
struct opentable
{
struct openttableitem
{
char name[9]; /*文件名*/
int firstdisk; /*起始盘块号*/
int size; /*文件的大小*/ }openitem[MOFN];
int cur_size; /*当前打文件的数目*/
}; struct fatitem *fat; /*FAT表*/ struct direct *root; /*根目录*/ struct direct *cur_dir; /*当前目录*/ struct opentable u_opentable; /*文件打开表*/
int fd=-1; /*文件打开表的序号*/ char *bufferdir; /*记录当前路径的名称*/
char *fdisk; /*虚拟磁盘起始地址*/ void initfile();
void format();
void enter();
void halt();
int create(char *name);
int open(char *name);
int close(char *name);
int write(int fd,char *buf,int len);
int read(int fd,char *buf);
int del(char *name);
int mkdir(char *name);
int rmdir(char *name);
void dir();
int cd(char *name);
void print();
void show();
void initfile()
{
fdisk = (char *)malloc(MEM_D_SIZE*sizeof(char)); /*申请1M空间*/
format();
}
void format()
{
int i;
FILE *fp;
fat = (struct fatitem *)(fdisk+DISKSIZE); /*计算FAT表地址,引导区向后偏移1k)*/
/*-----初始化FAT表------------*/
fat[0].item=-1; /*引导块*/
fat[0].em_disk='1';
for(i=1;i { fat[i].item=i+1; fat[i].em_disk='1'; } fat[ROOT_DISK_NO].item=-1; /*存放根目录的磁盘块号*/ fat[ROOT_DISK_NO].em_disk='1'; for(i=ROOT_DISK_NO+1;i { fat[i].item = -1; fat[i].em_disk = '0'; } /*-----------------------------------------------*/ root = (struct direct *)(fdisk+DISKSIZE+FATSIZE); /*根目录的地址*/ /*初始化目录*/ /*---------指向当前目录的目录项---------*/ root->directitem[0].sign = 1; root->directitem[0].firstdisk = ROOT_DISK_NO; strcpy(root->directitem[0].name," ."); root->directitem[0].next = root->directitem[0].firstdisk; root->directitem[0].property = '1'; root->directitem[0].size = ROOT_DISK_SIZE; /*-------指向上一级目录的目录项---------*/ root->directitem[1].sign = 1; root->directitem[1].firstdisk = ROOT_DISK_NO; strcpy(root->directitem[1].name,". ."); root->directitem[1].next = root->directitem[0].firstdisk; root->directitem[1].property = '1'; root->directitem[1].size = ROOT_DISK_SIZE; if((fp = fopen("disk.dat","wb"))==NULL) { printf("Error:\n Cannot open file \n"); return; } for(i=2;i { root->directitem[i].sign = 0; root->directitem[i].firstdisk = -1; strcpy(root->directitem[i].name,"" ); root->directitem[i].next = -1; root->directitem[i].property = '0'; root->directitem[i].size = 0; } if((fp = fopen("disk.dat","wb"))==NULL) { printf("Error:\n Cannot open file \n"); return; } if(fwrite(fdisk,MEM_D_SIZE,1,fp)! =1) /*把虚拟磁盘空间保存到磁盘文件中*/ { printf("Error:\n File write error! \n"); } fclose(fp); } void enter() { FILE *fp; int i; fdisk = (char *)malloc(MEM_D_SIZE*sizeof(char)); /*申请1M空间*/ if((fp=fopen("disk.dat","rb"))==N ULL) { printf("Error:\nCannot open file\n"); return; } if(!fread(fdisk,MEM_D_SIZE,1,fp)) /*把磁盘文件disk.dat 读入虚拟磁盘空间(内存)*/ { printf("Error:\nCannot read file\n"); exit(0); } fat = (struct fatitem *)(fdisk+DISKSIZE); /*找到FAT表地 址*/ root = (struct direct *)(fdisk+DISKSIZE+FATSIZE);/*找到根目录地址*/ fclose(fp); /*--------------初始化用户打开表------------------*/ for(i=0;i { strcpy(u_opentable.openitem[i].n ame,""); u_opentable.openitem[i].firstdisk = -1; u_opentable.openitem[i].size = 0; } u_opentable.cur_size = 0; cur_dir = root; /*当前目录为根目录*/ bufferdir = (char *)malloc(DIR_MAXSIZE*sizeof(char)); strcpy(bufferdir,"Root:"); } void halt() { FILE *fp; int i; if((fp=fopen("disk.dat","wb"))==N ULL) { printf("Error:\nCannot open file\n"); return; } if(!fwrite(fdisk,MEM_D_SIZE,1,fp)) /*把虚拟磁盘空间(内存)内容读入磁盘文件disk.dat */ { printf("Error:\nFile write error!\n"); } fclose(fp); free(fdisk); free(bufferdir); return; } int create(char *name) { int i,j; if(strlen(name)>8) /*文件名大于8位*/ return(-1); for(j=2;j if(!strcmp(cur_dir->directitem[j].n ame,name)) break; } if(j return(-4); for(i=2;i { if(cur_dir->directitem[i].firstdisk== -1) break; } if(i>=MSD+2) /*无空目录项*/ return(-2); if(u_opentable.cur_size>=MOFN) /*打开文件太多*/ return(-3); for(j=ROOT_DISK_NO+1;j if(fat[j].em_disk=='0') break; } if(j>=DISK_NUM) return(-5); fat[j].em_disk = '1'; /*将空闲块置为已经分配*/ /*-----------填写目录项-----------------*/ strcpy(cur_dir->directitem[i].name,na me); cur_dir->directitem[i].firstdisk = j; cur_dir->directitem[i].size = 0; cur_dir->directitem[i].next = j; cur_dir->directitem[i].property = '0'; /*---------------------------------*/ fd = open(name); return 0; } int open(char *name) { int i, j; for(i=2;i { if(!strcmp(cur_dir->directitem[i].n ame,name)) break; } if(i>=MSD+2) return(-1); /*--------是文件还是目录-----------------------*/ if(cur_dir->directitem[i].property= ='1') return(-4); /*--------文件是否打开-----------------------*/ for(j=0;j { if(!strcmp(u_opentable.openitem[ j].name,name)) break; } if(j return(-2); if(u_opentable.cur_size>=MOFN) /*文件打开太多*/ return(-3); /*--------查找一个空闲用户打开表项-----------------------*/ for(j=0;j { if(u_opentable.openitem[j].firstdis k==-1) break; } /*--------------填写表项的相关信息------------------------*/ u_opentable.openitem[j].firstdisk = cur_dir->directitem[i].firstdisk; strcpy(u_opentable.openitem[j].name, name); u_opentable.openitem[j].size = cur_dir->directitem[i].size; u_opentable.cur_size++; /*----------返回用户打开表表项的序号--------------------------*/ return(j); } int close(char *name) { int i; for(i=0;i { if(!strcmp(u_opentable.openitem[ i].name,name)) break; } if(i>=MOFN) return(-1); /*-----------清空该文件的用户打开表项的内容---------------------*/ strcpy(u_opentable.openitem[i].name, ""); u_opentable.openitem[i].firstdisk = -1; u_opentable.openitem[i].size = 0; u_opentable.cur_size--; return 0; } int write(int fd, char *buf, int len) { char *first; int item, i, j, k; int ilen1, ilen2, modlen, temp; /*----------用$ 字符作为空格# 字符作为换行符-----------------------*/ char Space = 32; char Endter= '\n'; for(i=0;i { if(buf[i] == '$') buf[i] = Space; else if(buf[i] == '#') buf[i] = Endter; } /*----------读取用户打开表对应表项第一个盘块号-----------------------*/ item = u_opentable.openitem[fd].firstdisk; /*-------------找到当前目录所对应表项的序号-------------------------*/ for(i=2;i { if(cur_dir->directitem[i].firstdisk== item) break; } temp = i; /*-存放当前目录项的下标-*/ /*------找到的item 是该文件的最后一块磁盘块-------------------*/ while(fat[item].item!=-1) { item =fat[item].item; /*-查找该文件的下一盘块--*/ } /*-----计算出该文件的最末地址-------*/ first = fdisk+item*DISKSIZE+u_opentable.ope nitem[fd].size%DISKSIZE; /*-----如果最后磁盘块剩余的大小大于要写入的文件的大小-------*/ if(DISKSIZE-u_opentable.openite m[fd].size%DISKSIZE>len) { strcpy(first,buf); u_opentable.openitem[fd].size = u_opentable.openitem[fd].size+len; cur_dir->directitem[temp].size = cur_dir->directitem[temp].size+len; } else { for(i=0;i<(DISKSIZE-u_opentable. openitem[fd].size%DISKSIZE);i++) {/*写一部分内容到最后一块磁盘块的剩余空间(字节)*/ first[i] = buf [i]; } /*-----计算分配完最后一块磁盘的剩余空间(字节) 还剩下多少字 节未存储-------*/ ilen1 = len-(DISKSIZE-u_opentable.openitem [fd].size%DISKSIZE); ilen2 = ilen1/DISKSIZE; modlen = ilen1%DISKSIZE; if(modlen>0) ilen2 = ilen2+1; /*--还需要多少块磁盘块-*/ for(j=0;j { for(i=ROOT_DISK_NO+1;i { if(fat[i].em_disk=='0') break; } if(i>=DISK_NUM) /*--如果磁盘块已经分配完了-*/ return(-1); first = fdisk+i*DISKSIZE; /*--找到的那块空闲磁盘块的起始地址-*/ if(j==ilen2-1) /*--如果是最后要分配的一块-*/ { for(k=0;k first[k] = buf[k]; } else/*-如果不是要最后分配的一块--*/ { for(k=0;k first[k] =buf[k]; } fat[item].item = i; /*--找到一块后将它的序号存放在上一块的指针中-*/ fat[i].em_disk = '1'; /*--置找到的磁盘快的空闲标志位为已分配-*/ fat[i].item = -1; /*--它的指针为-1 (即没有下一块)-*/ } /*--修改长度-*/ u_opentable.openitem[fd].size = u_opentable.openitem[fd].size+len; cur_dir->directitem[temp].size = cur_dir->directitem[temp].size+len; } return 0; } int read(int fd, char *buf) { int len = u_opentable.openitem[fd].size; char *first; int i, j, item; int ilen1, modlen; item = u_opentable.openitem[fd].firstdisk; ilen1 = len/DISKSIZE; modlen = len%DISKSIZE; if(modlen!=0) ilen1 = ilen1+1; /*--计算文件所占磁盘的块数-*/ first = fdisk+item*DISKSIZE; /*--计算文件的起始位置-*/ for(i=0;i { if(i==ilen1-1) /*--如果在最后一个磁盘块-*/ { for(j=0;j buf[i*DISKSIZE+j] = first[j]; } else /*--不在最后一块磁盘块 -*/ { for(j=0;j buf[i*DISKSIZE+j] = first[j]; item = fat[item].item; /*-查找下一盘块-*/ first = fdisk+item*DISKSIZE; } } return 0; } int del(char *name) { int i,cur_item,item,temp; for(i=2;i { if(!strcmp(cur_dir->directitem[i].n ame,name)) break; } cur_item = i; /*--用来保存目录项的序号,供释放目录中-*/ if(i>=MSD+2) /*--如果不在当前目录中-*/ return(-1); if(cur_dir->directitem[cur_item].p roperty!='0') /*--如果删除的(不)是目录-*/ return(-3); for(i=0;i { if(!strcmp(u_opentable.openitem[ i].name,name)) return(-2); } item = cur_dir->directitem[cur_item].firstdisk; /*--该文件的起始盘块号-*/ while(item!=-1) /*--释放空间,将FAT表对应项进行修改-*/ { temp = fat[item].item; fat[item].item = -1; fat[item].em_disk = '0'; item = temp; } /*-----------------释放目录项-----------------------*/ cur_dir->directitem[cur_item].sign = 0; cur_dir->directitem[cur_item].first disk = -1; strcpy(u_opentable.openitem[cur_ item].name,""); cur_dir->directitem[cur_item].next = -1; cur_dir->directitem[cur_item].propert y = '0'; cur_dir->directitem[cur_item].size = 0; return 0; } int mkdir(char *name) { int i,j; struct direct *cur_mkdir; if(!strcmp(name,".")) return(-4); if(!strcmp(name,"..")) return(-4); if(strlen(name)>8) /*-如果目录名长度大于8位-*/ return(-1); for(i=2;i { if(cur_dir->directitem[i].firstdisk== -1) break; } if(i>=MSD+2) /*-目录/文件已满-*/ return(-2); for(j=2;j { if(!strcmp(cur_dir->directitem[j].n ame,name)) break; } if(j return(-3); for(j=ROOT_DISK_NO+1;j { if(fat[j].em_disk=='0') break; } if(j>=DISK_NUM) return(-5); fat[j].em_disk='1'; /*-将该空闲块设置为已分配-*/ /*-------------填写目录项----------*/ strcpy(cur_dir->directitem[i].name ,name); cur_dir->directitem[i].firstdisk=j; cur_dir->directitem[i].size=ROOT_ DISK_SIZE; cur_dir->directitem[i].next=j; cur_dir->directitem[i].property='1'; /*-所创目录在虚拟磁盘上的地址(内存物理地址)-*/ cur_mkdir=(struct direct *)(fdisk+cur_dir->directitem[i].firstdisk *DISKSIZE); /*-初始化目录-*/ /*-指向当前目录的目录项-*/ cur_mkdir->directitem[0].sign=0; cur_mkdir->directitem[0].firstdisk =cur_dir->directitem[i].firstdisk; strcpy(cur_mkdir->directitem[0].n ame,"."); cur_mkdir->directitem[0].next=cu r_mkdir->directitem[0].firstdisk; cur_mkdir->directitem[0].propert y='1'; cur_mkdir->directitem[0].size=RO OT_DISK_SIZE; /*-指向上一级目录的目录项-*/ cur_mkdir->directitem[1].sign=cur _dir->directitem[0].sign; cur_mkdir->directitem[1].firstdisk= cur_dir->directitem[0].firstdisk; strcpy(cur_mkdir->directitem[1].n ame,".."); cur_mkdir->directitem[1].next=cur _mkdir->directitem[1].firstdisk; cur_mkdir->directitem[1].property ='1'; cur_mkdir->directitem[1].size=RO OT_DISK_SIZE; for(i=2;i { cur_mkdir->directitem[i].sign=0; cur_mkdir->directitem[i].firstdisk= -1; strcpy(cur_mkdir->directitem[i].na me,""); cur_mkdir->directitem[i].next=-1; cur_mkdir->directitem[i].property ='0'; cur_mkdir->directitem[i].size=0; } return 0; } int rmdir(char *name) { int i,j,item; struct direct *temp_dir; /*-检查当前目录项中有无该目录-*/ for(i=2;i { if(!strcmp(cur_dir->directitem[i].n ame,name)) break; } if(i>=MSD+2) /*-没有这个文件或目录-*/ return(-1); if(cur_dir->directitem[i].property! ='1')/*-删除的不是目录-*/ return(-3); /*-判断要删除的目录有无子目录-*/ temp_dir=(struct direct *)(fdisk+cur_dir->directitem[i].next*DI SKSIZE); for(j=2;j { if(temp_dir->directitem[j].next!=-1) break; } if(j return(-2); /*------------找到起始盘块号,并将其释放----------------*/ item=cur_dir->directitem[i].firstdis k; fat[item].em_disk='0'; /*-修改目录项-*/ cur_dir->directitem[i].sign=0; cur_dir->directitem[i].firstdisk=-1; strcpy(cur_dir->directitem[i].name ,""); cur_dir->directitem[i].next=-1; cur_dir->directitem[i].property='0' ; cur_dir->directitem[i].size=0; return 0; } void dir() { int i; for(i=2;i { if(cur_dir->directitem[i].firstdisk!= -1) /*-如果存在子目录-*/ { printf("%s\t",cur_dir->directitem[i] .name); if(cur_dir->directitem[i].property= ='0') /*-文件-*/ printf("%d\t\t\n",cur_dir->directite m[i].size); else printf("\t<目录>\t\n"); } } } int cd(char *name) { int i,j,item; char *str; char *temp,*point,*point1; struct direct *temp_dir; temp_dir=cur_dir; str=name;