#include<string.h>
#include<stdlib.h>
#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=1i<ROOT_DISK_NO-1i++) /*存放 FAT表的磁盘块号*/
{
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+1i<DISK_NUMi++)
{
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=2i<MSD+2i++) /*-子目录初始化为空-*/
{
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"))==NULL)
{
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=0i<MOFNi++)
{
strcpy(u_opentable.openitem[i].name,"")
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"))==NULL)
{
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=2j<MSD+2j++) /*检查创建文件是否与已存在的文件重名*/
{
if(!strcmp(cur_dir->directitem[j].name,name))
break
}
if(j<MSD+2) /*文件已经存在*/
return(-4)
for(i=2i<MSD+2i++) /*找到第一个空闲子目录*/
{
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+1j<DISK_NUMj++) /*找到空闲盘块 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 = 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=2i<MSD+2i++) /*文件是否存在*/
{
if(!strcmp(cur_dir->directitem[i].name,name))
break
}
if(i>=MSD+2)
return(-1)
/*--------是文件还是目录-----------------------*/
if(cur_dir->directitem[i].property=='1')
return(-4)
/*--------文件是否打开-----------------------*/
for(j=0j<MOFNj++)
{
if(!strcmp(u_opentable.openitem[j].name,name))
break
}
if(j<MOFN) /*文件已经打开*/
return(-2)
if(u_opentable.cur_size>=MOFN) /*文件打开太多*/
return(-3)
/*--------查找一个空闲用户打开表项-----------------------*/
for(j=0j<MOFNj++)
{
if(u_opentable.openitem[j].firstdisk==-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=0i<MOFNi++)
{
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=0i<leni++)
{
if(buf[i] == '$')
buf[i] = Space
else if(buf[i] == '#')
buf[i] = Endter
}
/*----------读取用户打开表对应表项第一个盘块号-----------------------*/
item = u_opentable.openitem[fd].firstdisk
/*-------------找到当前目录所对应表项的序号-------------------------*/
for(i=2i<MSD+2i++)
{
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.openitem[fd].size%DISKSIZE
/*-----如果最后磁盘块剩余的大小大于要写入的文件的大小-------*/
if(DISKSIZE-u_opentable.openitem[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=0i<(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=0j<ilen2j++)
{
for(i=ROOT_DISK_NO+1i<DISK_NUMi++)/*寻找空闲磁盘块*/
{
if(fat[i].em_disk=='0')
break
}
if(i>=DISK_NUM) /*--如果磁盘块已经分配完了-*/
return(-1)
first = fdisk+i*DISKSIZE/*--找到的那块空闲磁盘块的起始地址-*/
if(j==ilen2-1) /*--如果是最后要分配的一块-*/
{
for(k=0k<len-(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE)-j*DISKSIZEk++)
first[k] = buf[k]
}
else/*-如果不是要最后分配的一块--*/
{
for(k=0k<DISKSIZEk++)
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=0i<ilen1i++)
{
if(i==ilen1-1) /*--如果在最后一个磁盘块-*/
{
for(j=0j<len-i*DISKSIZEj++)
buf[i*DISKSIZE+j] = first[j]
}
else /*--不在最后一块磁盘块-*/
{
for(j=0j<len-i*DISKSIZEj++)
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=2i<MSD+2i++) /*--查找要删除文件是否在当前目录中-*/
{
if(!strcmp(cur_dir->directitem[i].name,name))
break
}
说通俗一点就类似于数组加上链表的结构,i_addr[8]数组中每一个元素都指向了一个磁盘块,如果那个磁盘块中也存放了一个i_addr[8]数组,并且那个数组中的每个元素也指向了一个磁盘块,那么这就是二级的索引文件结构了~建议看一下 *** 作系统原理(庞丽萍)一书中的文件系统一章
这个东西是Unix V的一种典型的文件系统~呵呵~
常见的文件系统有FAT、NTFS、ExtFAT、ext2、ext3,reiserFS、VFAT、APFS。
1、FAT文件系统。
FAT文件系统诞生于1977年,它最初是为软盘设计的文件系统,但是后来随着微软推出dos和win 9×系统,FAT文件系统经过适配被逐渐用到了硬盘上,并且在那时的20年中,一直是主流的文件系统。
2、NTFS文件系统。
它是一种比FAT32功能更加强大的文件系统,从windows.2000后的windows系统的默认件装在NTFS格式的磁盘上。NTFS系统是一个日志性的文件系统,系统中对文件的 *** 作都可以被记录下来,当系统崩溃之后,利用日志功能可以修复数据。
3、ExtFAT文件系统。
ExFAT也是微软开发的文件系统,它是专门为闪存盘设计的文件系统,单个文件突破了4G的限制,而且分区的最大容量可达64ZB,建议512T B。ExFAT在windows,Linux以及Mac系统上,
都可以读写,作为U盘或者是移动硬盘的格式还
是比较合适的。
4、ext2文件系统。
ext2是为解决ext文件系统的缺陷而设计的可扩展的、高性能的文件系统,又被称为二级扩展文件系统。它是Linux文件系统中使用最多的类型,
并且在速度和CPU利用率上较为突出。ext2存取文件的性能极好,并可以支持256字节的长文件名,是GNU/Linux系统中标准的文件系统。
文件系统()
NTFS
NIFS
FAT32
exFAT
卷标)
的
格式化选项①)
5、ext3文件系统。
ext3是ext2文件系统的日志版本,它在ext2文件系统中增加了日志的功能。ext3提供了3种日志模式:日志(journal)、顺序(ordered)和回写
(writeback)。与ext2相比,ext3提供了更好的安全性以及向上向下的兼容性能。
6、reiserFS文件系统。
reiserFS是Linux环境下最稳定的日志文件系统之一,使用快速的平衡二叉树(binary tree)算法来查找磁盘上的自由空间和已有的文件,其搜索速度高于ext2,reiserFS能够像其他大多数文件系统一样,可动态的分配索引节,而无须在文件系统中创建固定的索引节。
7、VFAT文件系统。
VFAT主要用于处理长文件的一种文件名系统,它运行在保护模式下并使用VCACHE进行缓存,并具有和Windows系列文件系统和Linux文件系统兼容的特性。因此VFAT可以作为Windows和Lin ux交换文件的分区。
8、APFS文件系统。
APFS是苹果公司发布的新的文件格式,替代目前所使用的HFS+格式。这一全新文件系统专门针对闪存/SSD进行优化,提供了更强大的加密、写入时复制元数据、空间分享、文件和目录克隆、快照、目录大小快速调整、原子级安全存储基元,以及改进的文件系统底层技术。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)