操作系统课程设计文件系统模拟毕业设计(论文)word格式.doc
操作系统课程设计-文件系统模拟默认分类 2010-01-10 16:51:02 阅读102 评论0 字号:大中小 设计内容: 在Windows 2000/XP环境下,在U盘上创建一个数据文件来模仿微型计算机磁盘存储器,在此基础上建立磁盘文件系统。要求模拟编写完成模拟链接存储结构文件系统的一个文件复制命令(要求可以单个和成批复制文件)。 #include <iostream>#include <cstring>#include <conio.h>#include <iomanip>#define NAMELENGTH 21 /文件名的最大长度#define MAXFILE 20 /最大能拥有的文件个数#define PATH "G:disk.txt" /当作磁盘的文件disk.txt保存路径#define INT_NUM 250 /位示图有INT_NUM个int单元,这里可保存250 * 32 = 8000个记录块using namespace std;class FCB/文件控制块类public: FCB(char *filename = NULL, int ID = -1, int p = -1, int inum = 0); void Setfilename(char *filename); void SetID(int ID); void Setfp(int fp); void Setnotenum(int inum = 0); /设置inotenum int Getnotenum(); /返回inotenum void Notenum_addone(); /inotenum加1 char* Getfilename(); int GetID(); int Getfp(); private: char sFilenameNAMELENGTH; /文件名 int iID; /ID号 int fp; /头指针 int inotenum; /占用记录块个数;FCB:FCB(char *filename, int ID, int p, int inum) /构造函数 if (filename != NULL) strcpy(sFilename, filename); else strcpy(sFilename, "*"); iID = ID; fp = p; inotenum = inum;void FCB:Setnotenum(int inum) /设置该文件已占用的文件记录块数,默认形参值为0 inotenum = inum;void FCB:Notenum_addone() /该文件已占用的记录块数加1 inotenum +;int FCB:Getnotenum() /返回该文件已占用的记录块数 return inotenum;char* FCB:Getfilename()/ 返回文件名 return sFilename;int FCB:GetID()/返回文件ID号 return iID;int FCB:Getfp()/返回文件头指针 return fp;void FCB:Setfilename(char *filename) /设置文件名 if (filename != NULL) strcpy(sFilename, filename); else sFilename0 = '0' void FCB:SetID(int ID) /设置ID iID = ID;void FCB:Setfp(int p) /设置fp fp = p;class Filenoteblock /文件记录块类 public: char scontent10; /内容 int next; /块指针;class FCBTable /文件控制块表类 public: FCBTable(); int Search_free_note(unsigned &uflag, unsigned &n); /返回可用块地址 void Setbitmap(unsigned uflag, unsigned n); /修改位示图, 占有空闲块 void Freebitmap(int ip); /修改位示图, 释放空间 FCB stTableMAXFILE; /文件控制块表 int iFilenum; /已有文件控制块 int iusednum; /已占用的记录块数private: int ibitmapINT_NUM; /位示图, 最多可存入INI_NUM * 32个记录块;FCBTable:FCBTable() /构造函数 int i, n, mod, k, j; unsigned uflag; iFilenum = 0; /初始化为0 iusednum = 0; for (i=0; i<INT_NUM; i+) ibitmapi = 0; /将位示图的前n位置为1, dist.txt文件的前n个记录块用来存放文件控制块表 n = sizeof(FCBTable) / sizeof(Filenoteblock); if (sizeof(FCBTable) % sizeof(Filenoteblock) != 0) n +; i = n / 32; mod = n % 32; if (mod != 0)/不能整除 i +; for (k=0; k<i-1; k+) uflag = 1; for (j=0; j<32; j+) ibitmapk = ibitmapk | uflag; uflag = uflag << 1; uflag = 1; for (j=0; j<mod; j+) ibitmapi-1 = ibitmapi-1 | uflag; uflag = uflag << 1; else /整除 for (k=0; k<i; k+) uflag = 1; for (j=0; j<32; j+) ibitmapk = ibitmapk | uflag; uflag = uflag << 1; void FCBTable:Setbitmap(unsigned uflag, unsigned n) /修改位示图,占有空闲块 ibitmapn = ibitmapn | uflag;void FCBTable:Freebitmap(int ip) /释放空间 unsigned uflag; int i, j, k; i = ip / 32; j = ip % 32; uflag = 1; for (k=0; k<j; k+) uflag = uflag * 2; uflag = uflag; ibitmapi = ibitmapi & uflag;int FCBTable:Search_free_note(unsigned &uflag, unsigned &n) /寻找空闲块 unsigned i, j; for (i=0; i<250; i+) n = i; uflag = 1; for (j=0; j<32; j+) if (ibitmapi & uflag) = 0) return (i * 32 + j); uflag = uflag << 1; return -1;/寻找空闲的文件控制块, 若找到返回其它位置,否则返回-1int Search_free_FCB(FCBTable ftable) int i; for (i=0; i<MAXFILE; i+) if (strcmp(ftable.stTablei.Getfilename(), "*") = 0) return i; return -1;int Createfile(FCBTable &ftable, char *filename)/创建一个文件 int Fileexist(FCBTable ftable, char *name); FILE *fp; char buff10, c; int i, ip1, ip2; int iFCBlocate; /标记某文件在文件控制块表中的位置或空闲块位置 bool bFirsttime; Filenoteblock note1, note2; /文件记录块 unsigned uflag, n; if (filename = NULL) cout<<"无文件名, 文件创建失败!"<<endl; return -1; if (Fileexist(ftable, filename) != -1) cout<<"文件 "<<filename<<" 已存在, 创建失败!"<<endl; return -1; if (ftable.iFilenum = MAXFILE -1) cout<<"打开文件数已达到最大数量,文件创建失败!"<<endl; return -1; if (ftable.Search_free_note(uflag, n) = -1) /判断是否还有一空闲块 cout<<"无空闲空间, 文件创建失败!"<<endl; return -1; if (fp = fopen(PATH, "rb+") = NULL) /打开作为磁盘的文件 if (fp = fopen(PATH, "wb") = NULL) cout<<"文件创建失败!"<<endl; return -1; fclose(fp); if (fp = fopen(PATH, "rb+") = NULL) cout<<"文件创建失败!"<<endl; return -1; iFCBlocate = Search_free_FCB(ftable); /找到一个空闲块,上面保证了有 ftable.stTableiFCBlocate.Setfilename(filename); /注册文件名 ftable.stTableiFCBlocate.SetID(iFCBlocate);/注册文件ID cout<<" 下面请输入文件内容, 以 # 结束文件输入: "<<endl; fflush(stdin); c = getchar(); i = 0; bFirsttime = 1; ip1 = 0; while (c != '#') buffi = c; if (i = 9) if (ip1 = ftable.Search_free_note(uflag, n) != -1) /寻找一个空闲块 ftable.Setbitmap(uflag, n); ftable.iusednum +; ftable.stTableiFCBlocate.Notenum_addone(); /此文件占用记录块加1, 构造函数初始化其为0 else cout<<"外部空间已满, 不能再保存数据!"<<endl; break; if (bFirsttime = 1) ftable.stTableiFCBlocate.Setfp(ip1); /设置头指针 else note2.next = ip1; fseek(fp, ip2 * sizeof(Filenoteblock), 0); fwrite(¬e2, sizeof(Filenoteblock), 1, fp); strcpy(note1.scontent, buff); note2 = note1; ip2 = ip1; i = 0; bFirsttime = 0; /if else i +; c = getchar(); /while /因无空闲块而退出循环,将上一块数据保存.上面已保证至少有一块空闲块 if (ip1 = -1) note2.next = -1; fseek(fp, ip2 * sizeof(Filenoteblock), 0); fwrite(¬e2, sizeof(Filenoteblock), 1, fp); fclose(fp); ftable.iFilenum +; return 1; /不是因为无空闲块而退出循环 if (i != 0) /不刚好为10个字符 if (ip1 = ftable.Search_free_note(uflag, n) != -1) /寻找一个空闲块, 且有 ftable.Setbitmap(uflag, n); ftable.iusednum +; ftable.stTableiFCBlocate.Notenum_addone(); /此文件占用记录块加1 strcpy(note1.scontent, buff); note1.scontenti = '0' if (bFirsttime = 1) /第一个记录块 ftable.stTableiFCBlocate.Setfp(ip1); /设置头指针 note1.next = -1; fseek(fp, ip1 * sizeof(Filenoteblock), 0); fwrite(¬e1, sizeof(Filenoteblock), 1, fp); else /不为第一个记录块 /将上一块写入disk.txt文件 note2.next = ip1; fseek(fp, ip2 * sizeof(Filenoteblock), 0); fwrite(¬e2, sizeof(Filenoteblock), 1, fp); /将最后一块写入disk.txt文件 note1.next = -1; fseek(fp, ip1 * sizeof(Filenoteblock), 0); fwrite(¬e1, sizeof(Filenoteblock), 1, fp); else /没有空闲块,上面已保证不可能是第一块 note2.next = -1; fseek(fp, ip2 * sizeof(Filenoteblock), 0); fwrite(¬e2, sizeof(Filenoteblock), 1, fp); cout<<"外部空间已满, 不能再保存数据!"<<endl; else/刚好为10的整倍数个 if (ip1 = ftable.Search_free_note(uflag, n) != -1)/还有空闲块,则多加一个记录块 ftable.iusednum +; ftable.Setbitmap(uflag, n); ftable.stTableiFCBlocate.Notenum_addone(); /此文件占用记录块加1 note1.scontent0 = '0' note1.next = -1; note2.next = ip1; fseek(fp, ip2 * sizeof(Filenoteblock), 0); fwrite(¬e2, sizeof(Filenoteblock), 1, fp); fseek(fp, ip1 * sizeof(Filenoteblock), 0); fwrite(¬e1, sizeof(Filenoteblock), 1, fp); else /无空闲空间 note2.next = -1; fseek(fp, ip2 * sizeof(Filenoteblock), 0); fwrite(¬e2, sizeof(Filenoteblock), 1, fp); ftable.iFilenum +; /文件数加1 fclose(fp); return 1;void Printfile(FCBTable ftable, char *name) /输出指定文件的内容 int i, j, ip; FILE *fp; Filenoteblock note; if (name = NULL) cout<<"无文件名, 请确认已输入文件名!"<<endl; return; cout<<endl<<" " for (i=0; i<MAXFILE; i+) if (strcmp(ftable.stTablei.Getfilename(), name) = 0) if (fp = fopen(PATH, "rb") = NULL) cout<<"磁盘文件打开失败!"<<endl; return; ip = ftable.stTablei.Getfp(); while (ip != -1) fseek(fp, ip * sizeof(Filenoteblock), 0); fread(¬e, sizeof(Filenoteblock), 1, fp); for (j=0; j<10; j+) if (note.scontentj != '0') if (note.scontentj != '#') cout<<note.scontentj; else cout<<endl; break; else break; ip = note.next; fclose(fp); return; /if /for cout<<"无文件名为 "<<name<<" 的文件!"<<endl;/增加一个放源文件的数组空间,isourcenum没在这里加1int Expand_source_space(char *&source, int isourcenum) char *source2; int i, j; /申请新内存 source2 = new char*isourcenum + 1; if (source2 = NULL) cout<<" 内存不足, 数组扩展失败!"<<endl; return 0; for (i=0; i<=isourcenum; i+) source2i = new charNAMELENGTH; if (source2i = NULL) cout<<" 内存不足, 数组扩展失败!"<<endl; for (j=0; j<i; j+) deletesource2i; deletesource2; return 0; /初始化 for (j=0; j<NAMELENGTH - 1; j+) source2ij = '*' source2iNAMELENGTH - 1 = '0' if (source != NULL) /若原来有空间,source不为空 for (i=0; i<=isourcenum - 1; i+)/将原来的内容复制到新内存空间 strcpy(source2i, sourcei); /释放原来的空间 for (i=0; i<=isourcenum - 1; i+) deletesourcei; deletesource; source = source2; /将新分配的空间赋给source return 1;int Input_ds(char* &destination, char* &source, int &isourcenum)/输入目的文件名和源文件名 int j, k; char c; int iflag; /标记源文件内存扩展是否成功 destination = new charNAMELENGTH; cout<<"输入目的文件名: " cin>>destination; destinationNAMELENGTH - 1 = '0' /保证字符串输出正确 cout<<"依次输入源文件名, 中间用空格隔开: " source = NULL; isourcenum = -1;/比文件实际数目小1,正好和数组下标相符 fflush(stdin); c = getchar(); while (c != 'n') j = 0; while (c != 'n' && c = ' ') c = getchar(); while (c != 'n' && c != ' ' && j < NAMELENGTH - 1)/读文件名 if (j = 0) /开始一个新的源文件名,扩展源文件数组空间 isourcenum +; /源文件个数加1 iflag = Expand_source_space(source, isourcenum); if (iflag = 0) /扩展失败 cout<<" 源文件输入失败!"<<endl; isourcenum -; /回到原来的值 if (source != NULL) /已分配了一些空间 /释放已分配空间,并赋空 for (k=0; k<=isourcenum; k+) deletesourcek; deletesource; deletedestination; source = NULL; destination = NULL; isourcenum = -1; /没有源文件 return 0; sourceisourcenumj = c; c = getchar(); j +; /while (c != 'n' && c != ' ' && j < NAMELENGTH - 1) sourceisourcenumj = '0' while (j = NAMELENGTH - 1 && c != ' ')/将超过文件名长度的字符忽略 c = getchar(); /while return 1;/文件是否存在,存在返回在文件控制块表中的位置,否则返回 -1int Fileexist(FCBTable ftable, char *name) int i; for (i=0; i<MAXFILE; i+) if (strcmp(ftable.stTablei.Getfilename(), name) = 0) return i; return -1;/复制函数, 完全未复制返回0, 复制完成一部分返回1, 完全复制成功返回2/每向目的文件写入一次数据, 它占有的记录块就加1int Copyfile(char *destination, char *source, FCBTable &ftable, int isourcenum) int ipd, ipd2, ips, i, j; int idlocate, islocate; /分别标记目的文件和源文件在文件控制块表中的位置 FILE *fp; Filenoteblock notes, noted, noted2; bool bover; /标记目的文件原来的记录块是否被覆盖完 bool bfirsttime; unsigned uflag, n; if (destination = NULL | source = NULL) cout<<"没有输入目的文件或源文件, 请确定已输入!"<<endl; return 0; if (fp = fopen(PATH, "rb+") = NULL) cout<<"文件 "<<PATH<<" 不存在, 请确定创建了此文件!"<<endl; return 0; idlocate = Fileexist(ftable, destination); if (idlocate != -1)/目的文件已存在 ipd = ftable.stTableidlocate.Getfp(); /取得头指针 ftable.stTableidlocate.Setnotenum(0); /设置占用记录块为0 bover = 0; else /不存在 idlocate = Search_free_FCB(ftable); if (idlocate = -1) /无空闲文件控制块 cout<<" 无空闲文件控制块, 无法新建目的文件, 复制任务失败!"<<endl; fclose(fp); return 0; if (ftable.Search_free_note(uflag, n) != -1)/有空闲记录块空间 ftable.stTableidlocate.Setfilename(destination); /注册文件名 ftable.stTableidlocate.SetID(idlocate); /设置文件ID bover = 1; else/无空闲空间 cout<<"无剩余空间可使用, 复制失败!"<<endl; fclose(fp); return 0; bfirsttime = 1; noted.scontent0 = '#' noted.scontent1 = '0' for (i=0; i<=isourcenum; i+) islocate = Fileexist(ftable, sourcei); if ( islocate != -1)/该源文件存在 ips = ftable.stTableislocate.Getfp();/取得源文件头指针 while (ips != -1) /从源文件中读出一块数据 fseek(fp, ips * sizeof(Filenoteblock), 0); fread(¬es, sizeof(Filenoteblock), 1, fp); /目的文件原块未覆盖完,取出将被覆盖的块,以取得下一块的指针 if (bover = 0) fseek(fp, ipd * sizeof(Filenoteblock), 0); fread(¬ed, sizeof(Filenoteblock), 1, fp); else /已覆盖完 bover = 1 if (ipd = ftable.Search_free_note(uflag, n) != -1)/有空闲空间 ftable.iusednum +; ftable.Setbitmap(uflag, n); if (bfirsttime = 1) /第一次, 说明目的文件不存在 ftable.stTableidlocate.Setfp(ipd); /设置头指针 ftable.iFilenum +; /已有文件数加1 else /没有空闲空间, 不会是第一次就无空闲空间 noted2.next = -1; fseek(fp, ipd2 * sizeof(Filenoteblock), 0); fwrite(¬ed2, sizeof(Filenoteblock), 1, fp); ftable.stTableidlocate.Notenum_addone(); /此文件占用记录块加1 fclose(fp); return 1; strcpy(noted.scontent, notes.scontent); /赋给要写入目的文件的块 for (j=0; j<10; j+) if (noted.scontentj = '0') noted.scontentj = '#' break; if (bfirsttime = 0) /不是第一次 /写入目的文件 noted2.next = ipd; fseek(fp, ipd2 * sizeof(Filenoteblock), 0); fwrite(¬ed2, sizeof(Filenoteblock), 1, fp); ftable.stTableidlocate.Notenum_addone(); /此文件占用记录块加1 /noted2, ipd2保存noted, ipd的前一个值 noted2 = noted; ipd2 = ipd; if (bover = 0 && noted.next = -1)/目的文件存在且原来的块覆盖完 bover = 1; ips = notes.next; /修改源文件指针 /修改目的文件指针 if (bover = 0) /若目的文件原来的块没覆盖完,取目的文件下一块 ipd = noted.next; bfirsttime = 0; /whil