本周进行操作系统课程设计,在很多的题目中选了个unix文件系统模拟,主要就是操作结构与文件。
为了方便,文件系统结构如下:
Super block -- Block bitmap -- Inode bitmap -- Inode table -- Block zone
其中:
Super block: 存储基本信息
Block bitmap:块分配情况
Inode bitmap:索引节点分配情况
Inode table: Indoe 节点存放区
Block zone:存放数据区
效果如下:
总的说来,做的还是挺简单的,只是实现了基本的功能.而块的分配没有怎么完成,linux系统中一般是通过多级索引的方式为inode分配块.
刚开始我的想法是:inode的块(512B)只写510B,留下2B用于记录下一块的块号,我觉得应该可行,但觉得繁,就没有写下去.所以就没有多余的
块分配操作.知识INode对应一个Block....,太懒了.还有一个缺点,文件指针移动太频繁了,而且都是绝对定位移动(好算,呵呵)
代码如下:
/*核心思想:一切皆是文件 如果是目录:Block中存储的是目录下文件和目录的fcb 如果是文件:Block中存储的是文件的内容 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #include <signal.h> #define BLOCKSIZE 512 #define BLOCKNUM 512 #define INODENUM 30 #define FILENAME "file.dat" typedef struct{ unsigned short blockSize; unsigned short blockNum; unsigned short inodeNum; unsigned short blockFree; unsigned short inodeFree; }SuperBlock; typedef struct{ unsigned short inum; char fileName[10]; unsigned short isDir; // 0-file 1-dir unsigned short iparent; unsigned short length; //if file->filesize if dir->filenum unsigned short blockNum; }Inode,*PtrInode; //Fcb用于存储文件与 目录信息,主要用途:将一个目录下的所有文件(包括目录)写入到该目录对应的Block中 typedef struct { unsigned short inum; char fileName[10]; unsigned short isDir; }Fcb,*PtrFcb; typedef struct{ char userName[10]; char passWord[10]; }User; char blockBitmap[BLOCKNUM]; char inodeBitmap[INODENUM]; SuperBlock superBlock; User curUser=(User){"root","root"}; unsigned short currentDir; //current inodenum FILE *fp; const unsigned short superBlockSize=sizeof(superBlock); const unsigned short blockBitmapSize=sizeof(blockBitmap); const unsigned short inodeBitmapSize=sizeof(inodeBitmap); const unsigned short inodeSize=sizeof(Inode); const unsigned short fcbSize=sizeof(Fcb); char *argv[5]; int argc; void createFileSystem() /*创建*/ { long len; PtrInode fileInode; if ((fp=fopen(FILENAME,"wb+"))==NULL) { printf("open file %s error...\n",FILENAME); exit(1); } //init bitmap for(len=0;len<BLOCKNUM;len++) blockBitmap[len]=0; for(len=0;len<INODENUM;len++) inodeBitmap[len]=0; //memset for (len=0;len<(superBlockSize+blockBitmapSize+inodeBitmapSize+inodeSize*INODENUM+BLOCKSIZE*BLOCKNUM);len++) { fputc(0,fp); } rewind(fp); //init superBlock superBlock.blockNum=BLOCKNUM; superBlock.blockSize=BLOCKSIZE; superBlock.inodeNum=INODENUM; superBlock.blockFree=BLOCKNUM-1; superBlock.inodeFree=INODENUM-1; fwrite(&superBlock,superBlockSize,1,fp); //create root fileInode=(PtrInode)malloc(inodeSize); fileInode->inum=0; strcpy(fileInode->fileName,"/"); fileInode->isDir=1; fileInode->iparent=0; fileInode->length=0; fileInode->blockNum=0; //write / info to file inodeBitmap[0]=1; blockBitmap[0]=1; fseek(fp,superBlockSize,SEEK_SET); fwrite(blockBitmap,blockBitmapSize,1,fp); fseek(fp,superBlockSize+blockBitmapSize,SEEK_SET); fwrite(inodeBitmap,inodeBitmapSize,1,fp); fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize,SEEK_SET); fwrite(fileInode,inodeSize,1,fp); fflush(fp); //point to currentDir currentDir=0; } void openFileSystem() /*如果FILENAME可读,则代表之前已有信息,并读取相应数据 如果不可读,则创建文件系统 */ { if((fp=fopen(FILENAME,"rb"))==NULL) { createFileSystem(); } else { if ((fp=fopen(FILENAME,"rb+"))==NULL) { printf("open file %s error...\n",FILENAME); exit(1); } rewind(fp); //read superBlock from file fread(&superBlock,superBlockSize,1,fp); //read bitmap from file fread(blockBitmap,blockBitmapSize,1,fp); fread(inodeBitmap,inodeBitmapSize,1,fp); //init current dir currentDir=0; } } void createFile(char *name,int flag) //flag=0 ->create file =1 ->directory { int i,nowBlockNum,nowInodeNUm; PtrInode fileInode=(PtrInode)malloc(inodeSize); PtrInode parentInode=(PtrInode)malloc(inodeSize); PtrFcb fcb=(PtrFcb)malloc(fcbSize); //the available blockNumber for(i=0;i<BLOCKNUM;i++) { if(blockBitmap[i]==0) { nowBlockNum=i; break; } } //the available inodeNumber for(i=0;i<INODENUM;i++) { if(inodeBitmap[i]==0) { nowInodeNUm=i; break; } } //init fileINode struct fileInode->blockNum=nowBlockNum; strcpy(fileInode->fileName,name); fileInode->inum=nowInodeNUm; fileInode->iparent=currentDir; if(flag==0) { fileInode->isDir=0; } else { fileInode->isDir=1; } fileInode->length=0; //write fileInfo to file fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+inodeSize*nowInodeNUm,SEEK_SET); fwrite(fileInode,inodeSize,1,fp); //update superBlock and bitmap superBlock.blockFree-=1; superBlock.inodeFree-=1; blockBitmap[nowBlockNum]=1; inodeBitmap[nowInodeNUm]=1; //init fcb info strcpy(fcb->fileName,fileInode->fileName); fcb->inum=fileInode->inum; fcb->isDir=fileInode->isDir; //update to file ... //update parent dir block info fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+currentDir*inodeSize,SEEK_SET); fread(parentInode,inodeSize,1,fp); fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+INODENUM*inodeSize+parentInode->blockNum*BLOCKSIZE+parentInode->length*fcbSize,SEEK_SET); fwrite(fcb,fcbSize,1,fp); //update parent dir inode info parentInode->length+=1; fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+currentDir*inodeSize,SEEK_SET); fwrite(parentInode,inodeSize,1,fp); // free resource free(fileInode); free(parentInode); free(fcb); } void list() { int i; PtrFcb fcb=(PtrFcb)malloc(fcbSize); PtrInode parentInode=(PtrInode)malloc(inodeSize); //read parent inode info from file fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+currentDir*inodeSize,SEEK_SET); fread(parentInode,inodeSize,1,fp); //point to parent dir block fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+inodeSize*INODENUM+parentInode->blockNum*BLOCKSIZE,SEEK_SET); //list info for(i=0;i<parentInode->length;i++) { fread(fcb,fcbSize,1,fp); printf("Filename: %-10s",fcb->fileName); printf("Inode number: %-2d ",fcb->inum); if(fcb->isDir==1) { printf("Directory\n"); } else { printf("Regular file\n"); } } //free resource free(fcb); free(parentInode); } int findInodeNum(char *name,int flag) //flag=0 ->find file flag=1 -> find dir { int i,fileInodeNum; PtrInode parentInode=(PtrInode)malloc(inodeSize); PtrFcb fcb=(PtrFcb)malloc(fcbSize); //read current inode info from file fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+currentDir*inodeSize,SEEK_SET); fread(parentInode,inodeSize,1,fp); //read the fcb in the current dir block fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+inodeSize*INODENUM+parentInode->blockNum*BLOCKSIZE,SEEK_SET); for(i=0;i<parentInode->length;i++) { fread(fcb,fcbSize,1,fp); if(flag==0) { if((fcb->isDir==0)&&(strcmp(name,fcb->fileName)==0)) { fileInodeNum=fcb->inum; break; } } else { if((fcb->isDir==1)&&(strcmp(name,fcb->fileName)==0)) { fileInodeNum=fcb->inum; break; } } } if(i==parentInode->length) fileInodeNum=-1; free(fcb); free(parentInode); return fileInodeNum; } void cd(char *name) { int fileInodeNum; PtrInode fileInode=(PtrInode)malloc(inodeSize); if(strcmp(name,"..")!=0) { fileInodeNum=findInodeNum(name,1); if(fileInodeNum==-1) printf("This is no %s directory...\n",name); else { currentDir=fileInodeNum; } } else { fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+currentDir*inodeSize,SEEK_SET); fread(fileInode,inodeSize,1,fp); currentDir=fileInode->iparent; } free(fileInode); } void cdParent() { PtrInode fileInode=(PtrInode)malloc(inodeSize); fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+currentDir*inodeSize,SEEK_SET); fread(fileInode,inodeSize,1,fp); currentDir=fileInode->iparent; free(fileInode); } void write(char *name) { int fileInodeNum,i=0; char c; PtrInode fileInode=(PtrInode)malloc(inodeSize); if((fileInodeNum=findInodeNum(name,1))!=-1) { printf("This is a directory,not a file...\n"); return; } fileInodeNum=findInodeNum(name,0); if(fileInodeNum==-1) printf("This is no %s file...\n",name); else { //get inode->blocknum fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+fileInodeNum*inodeSize,SEEK_SET); fread(fileInode,inodeSize,1,fp); //point to the block site fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+INODENUM*inodeSize+fileInode->blockNum*BLOCKSIZE,SEEK_SET); printf("please input file content(stop by #):\n"); while((c=getchar())!='#') { fputc(c,fp); i++; } //update inode->length fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+fileInodeNum*inodeSize,SEEK_SET); fread(fileInode,inodeSize,1,fp); fileInode->length=i-1; fseek(fp,-inodeSize,SEEK_CUR); fwrite(fileInode,inodeSize,1,fp); } free(fileInode); } void read(char *name) { int fileInodeNum; char c; PtrInode fileInode=(PtrInode)malloc(inodeSize); if((fileInodeNum=findInodeNum(name,1))!=-1) { printf("This is a directory,not a file...\n"); return; } fileInodeNum=findInodeNum(name,0); if(fileInodeNum==-1) printf("This is no %s file...\n",name); else { //get inode->blocknum fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+fileInodeNum*inodeSize,SEEK_SET); fread(fileInode,inodeSize,1,fp); //point to the block site fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+INODENUM*inodeSize+fileInode->blockNum*BLOCKSIZE,SEEK_SET); //read content if(fileInode->length!=0) { while((c=fgetc(fp))!=EOF) { putchar(c); } printf("\n"); } } free(fileInode); } void delete(char *name) /*delete 一个文件,需要修改SuperBlock,Blockbitmap,Inodebitmap,并更新父节点长度,删除父节点Block中存储的该文件fcb*/ { int fileInodeNum,i; PtrInode fileInode=(PtrInode)malloc(inodeSize); PtrInode parentInode=(PtrInode)malloc(inodeSize); Fcb fcb[20]; if(((fileInodeNum=findInodeNum(name,0))==-1)&&((fileInodeNum=findInodeNum(name,1))==-1)) { printf("This is no %s...\n",name); } else { if((fileInodeNum=findInodeNum(name,0))==-1) { fileInodeNum=findInodeNum(name,1); } fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+fileInodeNum*inodeSize,SEEK_SET); fread(fileInode,inodeSize,1,fp); fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+fileInode->iparent*inodeSize,SEEK_SET); fread(parentInode,inodeSize,1,fp); //update parent info fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+INODENUM*inodeSize+parentInode->blockNum*BLOCKSIZE,SEEK_SET); for(i=0;i<parentInode->length;i++) { fread(&fcb[i],fcbSize,1,fp); //fcb[i]=tmp; } fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+INODENUM*inodeSize+parentInode->blockNum*BLOCKSIZE,SEEK_SET); for(i=0;i<BLOCKSIZE;i++) fputc(0,fp); fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+INODENUM*inodeSize+parentInode->blockNum*BLOCKSIZE,SEEK_SET); for(i=0;i<parentInode->length;i++) { if((strcmp(fcb[i].fileName,name))!=0) { fwrite(&fcb[i],fcbSize,1,fp); } } parentInode->length-=1; fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+fileInode->iparent*inodeSize,SEEK_SET); fwrite(parentInode,inodeSize,1,fp); //update bitmap inodeBitmap[fileInodeNum]=0; blockBitmap[fileInode->blockNum]=0; //update superblock superBlock.blockFree+=1; superBlock.inodeFree+=1; } free(fileInode); free(parentInode); } void updateResource() { rewind(fp); fwrite(&superBlock,superBlockSize,1,fp); fwrite(blockBitmap,blockBitmapSize,1,fp); fwrite(inodeBitmap,inodeBitmapSize,1,fp); fclose(fp); } void pathSet() { PtrInode curInode=(PtrInode)malloc(inodeSize); fseek(fp,superBlockSize+blockBitmapSize+inodeBitmapSize+currentDir*inodeSize,SEEK_SET); fread(curInode,inodeSize,1,fp); printf("%s@localhost:%s#",curUser.userName,curInode->fileName); free(curInode); } void systemInfo() { printf("Sum of block number:%d\n",superBlock.blockNum); printf("Each block size:%d\n",superBlock.blockSize); printf("Free of block number:%d\n",superBlock.blockFree); printf("Sum of inode number:%d\n",superBlock.inodeNum); printf("Free of inode number:%d\n",superBlock.inodeFree); } void help() { printf("command: \n\ help --- show help menu \n\ sysinfo --- show system base information \n\ cls --- clear the screen \n\ cd --- change directory \n\ mkdir --- make directory \n\ touch --- create a new file \n\ cat --- read a file \n\ write --- write something to a file \n\ logout --- exit user \n\ rm --- delete a directory or a file \n\ exit --- exit this system\n"); } int analyse(char *str) { int i; char temp[20]; char *ptr_char; char *syscmd[]={"help","ls","cd","mkdir","touch","cat","write","rm","logout","exit","sysinfo","cls"}; argc = 0; for(i = 0, ptr_char = str; *ptr_char != '\0'; ptr_char++) { if(*ptr_char != ' ') { while(*ptr_char != ' ' && (*ptr_char != '\0')) temp[i++] = *ptr_char++; argv[argc] = (char *)malloc(i+1); strncpy(argv[argc], temp, i); argv[argc][i] = '\0'; argc++; i = 0; if(*ptr_char == '\0') break; } } if(argc != 0) { for(i = 0; (i < 12) && strcmp(argv[0], syscmd[i]); i++); return i; } else return 12; return 0; } void login() { char userName[10]; char passWord[10]; while(1) { printf("login:"); gets(userName); system("stty -echo"); printf("passwd:"); gets(passWord); system("stty echo"); printf("\n"); if(strcmp(userName,curUser.userName)==0&&strcmp(passWord,curUser.passWord)==0) break; } } void stopHandle(int sig) { printf("\nPlease wait...,update resource\n"); updateResource(); exit(0); } void command(void) { char cmd[20]; do { pathSet(); gets(cmd); switch(analyse(cmd)) { case 0: help(); break; case 1: list(); break; case 2: cd(argv[1]); break; case 3: createFile(argv[1],1); break; case 4: createFile(argv[1],0); break; case 5: read(argv[1]); break; case 6: write(argv[1]); break; case 7: delete(argv[1]); break; case 8: updateResource(); login(); openFileSystem(); command(); break; case 9: updateResource(); exit(0); break; case 10: systemInfo(); break; case 11: system("clear"); break; default: break; } }while(1); } int main(int argc,char **argv){ signal(SIGINT,stopHandle); login(); openFileSystem(); command(); return 0; }