【课程设计|C++】操作系统:文件系统

海轰Pro

共 13974字,需浏览 28分钟

 · 2021-07-07

文件系统

题目描述

1、实验内容

    通过一个简单的二级文件系统设计,加深对文件系统的内部功能以及内部实现的理解。要求模拟采用二级目录结构的磁盘文件系统的文件操作能实现以下几条命令,用输入命令来模拟用户程序中调用的文件操作:

  • Login 用户登录
  • Dir 列文件目录(列出文件名、物理地址、保护码和文件长度)
  • Create 创建文件
  • Delete 删除文件
  • Open 打开文件
  • Close 关闭文件
  • Read 读文件
  • Write 写文件
  • 源文件可以进行读写保护

2、实验原理

    文件系统管理中用到的数据结构有:

  1. 首先应确定文件系统的数据结构:主目录、子目录及活动文件等。主目录和子目录都以文件的形式存放于磁盘,这样便于查找和修改。
  2. 用户创建的文件,可以编号存储于磁盘上。如:file0,file1,file2…并以编号作为物理地址,在目录中进行登记。

系统采用的开发环境

  • 软件:VC+ 6.0
  • 操作系统:Win 10

程序的流程图

图 1 系统框架
图 2 创建文件
图 3 新建用户
图 4 删除文件

程序功能段的说明及代码解释

1.用户注册

void userCreate()
{
 char c;
 char userName[10];
 int i;
 if(used<MaxUser)
 {
  cout<<"Please input username:";
  for(i=0;c=getch();i++)
  {
   if(c==13break;
   else
    userName[i]=c;
   printf("%c",c);
  }
  userName[i]='\0';
  for(i=0;i<used;i++)
  {
   if(!strcmp(userTable[i].userName,userName))
   {
    cout<<"\n";
    cout<<"该用户名已存在,创建用户失败!\n";
    system("pause");
    return;
   }
  }
  strcpy(userTable[used].userName,userName);
  cout<<"\n";
  cout<<"Please inout code:";
  for(i=0;c=getch();i++)
  {
   if(c==13break;
   else
    userTable[used].password[i]=c;
   printf("*");
  }
  userTable[userID].password[i]='\0';
  cout<<"\n";
  cout<<"用户创建成功!\n";
  used++;
  system("pause");
 }
 else
 {
  cout<<"创建用户失败,用户已达到上限!\n";
  system("pause");
 }
 fflush(stdin);// 清除读写缓冲区
}
图 5 用户注册
  1. 用户登录
int login()
{
 char name[10],psw[10];
 char c;
 int i,times;
 cout<<"Please input username:";
 for(i=0;c=getch();i++)
 {
  if(c==13break;
  else
   name[i]=c;
  printf("%c",c);
 }
 name[i]='\0';
 for(i=0;i<used;i++)
 {
  if(!strcmp(userTable[i].userName,name))
   break;
 }
 if(i==used)
 {
  cout<<"\n您输入的用户名不存在\n";
  system("pause");
  return -1;
 }
 for(times=0;times<3;times++)
 {
  memset(psw,'\0',sizeof(psw));
  cout<<"\nPlease input code:";
  for(i=0;c=getch();i++)
  {
   if(c==13break;
   else
    psw[i]=c;
   cout<<"*";
  }
  printf("\n");
  for(i=0;i<used;i++)
  {
   if(!strcmp(psw,userTable[i].password))
   {
    printf("用户登录成功\n");
    system("pause");
    break;
   }
  }
  if(i==used)
  {
   printf("您输入的密码错误,您还有%d次输入机会\n",2-times);
   if(times==2exit(0);
  }
  else break;
 }
 fflush(stdin);
 return i;
}
图 6 用户登录

3.创建新文件

void createFile(char fileName[],int length,char fileKind[])
{
 //int i,j;
 time_t rawtime;
 int startPos;
 UFD *fileNode,*p;
 for(p=userTable[userID].user->next;p!=NULL;p=p->next)
 {
  if(!strcmp(p->file->fileName,fileName))
  {
   printf("文件重名,创建文件失败\n");
   system("pause");
   return;
  }
 }
 if(requestDist(startPos,length))   //磁盘分配查询
 {
  fileNode=(UFD *)malloc(sizeof(UFD));
  fileNode->file=(fileTable *)malloc(sizeof(fileTable));  //这一步必不可少,因为fileNode里面的指针也需要申请地址,否则fileNode->file指向会出错
  strcpy(fileNode->file->fileName,fileName);
  strcpy(fileNode->file->fileKind,fileKind);
  fileNode->file->maxlength=length;
  fileNode->file->strat=startPos;
  fileNode->file->openFlag=false;
  time(&rawtime);
  fileNode->file->timeinfo=localtime(&rawtime);
  fileNode->next=NULL;
  if(userTable[userID].user->next==NULL)
   userTable[userID].user->next=fileNode;
  else
  {
   p=userTable[userID].user->next;
   while(p->next) p=p->next;
   p->next=fileNode;
  }
  printf("创建文件成功\n");
  system("pause");
 }
 else
 {
  printf("磁盘空间已满或所创建文件超出磁盘空闲容量,磁盘空间分配失败\n");
  system("pause");
 }
}
图 7 创建新文件

4.文件写入

void fileWrite(char fileName[])
{
 UFD *p,*q;
 q=userTable[userID].user;
 int i,k,startPos;
 for(p=q->next;p!=NULL;p=p->next)
 {
  if(!strcmp(p->file->fileName,fileName))
   break;
 }
 if(p)
 {
  if(!strcmp(p->file->fileKind,"r"))      //判断文件类型
  {
   printf("该文件是只读文件,写入失败\n");
   system("pause");
   return;
  }
  char str[500];
  printf("输入文件内容:\n");
  gets(str);
  startPos=p->file->strat;
  p->file->openFlag=true;    //文件打开标记
  p->file->length=strlen(str);
  if(p->file->length>p->file->maxlength)
  {
   printf("写入字符串长度大于该文件的总长度,写入失败\n");
   system("pause");
   return;
  }
  for(i=startPos,k=0;k<(int)strlen(str);i++,k++)
   disk[i]=str[k];
  printf("文件写入成功,请用close命令将该文件关闭\n");
  system("pause");
 }
 else
 {
  printf("没有找到该文件,请检查输入的文件名是否正确\n");
  system("pause");
 }
}
图 8 文件写入

5.关闭文件

void fileClose(char fileName[])
{
 UFD *p,*q;
 q=userTable[userID].user;
 for(p=q->next;p!=NULL;p=p->next)
 {
  if(!strcmp(p->file->fileName,fileName))
   break;
 }
 if(p) 
 {
  p->file->openFlag=false;
  printf("%s文件已关闭\n",p->file->fileName);
  system("pause");
 }
 else
 {
  printf("没有找到该文件,请检查输入的文件名是否正确!\n");
  system("pause");
 }
}
图 9 关闭文件

6.查看文件内容

void fileCat(char fileName[])
{
 int startPos,length;
 int k=0;
 UFD *p,*q;
 q=userTable[userID].user;
 for(p=q->next;p!=NULL;p=p->next)
 {
  if(!strcmp(p->file->fileName,fileName))
   break;
 }
 if(p)
 {
  startPos=p->file->strat;
  length=p->file->length;
  p->file->openFlag=true;    //文件打开标记
  for(int i=startPos;k<length;i++,k++)
  {
   if(i%50==0printf("\n");  //一行大于50个字符换行
   printf("%c",disk[i]);
  }
  printf("%s已被read进程打开,请用close命令将其关闭\n",p->file->fileName);
  system("pause");
 }
 else
 {
  printf("没有找到该文件,请检查输入的文件名是否正确\n");
  system("pause");
 }
}
图 10 查看文件内容

7.读取文件

void fileFine(char fileName[])
{
 UFD *p,*q;
 q=userTable[userID].user;
 for(p=q->next;p!=NULL;p=p->next)
 {
  if(!strcmp(p->file->fileName,fileName))
   break;
 }
 if(p)
 {
  printf("-------------------------------------------\n");
  printf("名字:%s\n",p->file->fileName);
  printf("长度:%d\n",p->file->maxlength);
  printf("起始地址:%d\n",p->file->strat);
  printf("类型:%s\n",p->file->fileKind);
  system("pause");
 }
 else
 {
  printf("没有找到该文件,请检查输入的文件名是否正确\n");
  system("pause");
 }
}
图 11 读取文件

8.显示用户所有文件

void fileDir(char userName[])
{
 UFD *p;
 int i,k;
 for(i=0;i<MaxUser;i++)
 {
  if(!strcmp(userTable[i].userName,userName))
  {
   k=i;break;
  }
 }
 if(i==MaxUser)
 {
  printf("没有找到该用户,请检查输入用户名是否正确\n");
  system("pause");
  return;
 }
 else
 {
  p=userTable[k].user->next;
  printf("----------------------------------------------------------\n");
  cout<<setw(10)<<"文件名称"<<setw(10)<<"文件长度"<<setw(10)<<"起始地址"<<setw(10)<<"文件类型"<<setw(30)<<"创建时间"<<endl;
  for(;p!=NULL;p=p->next)
     cout<<setw(10)<<p->file->fileName<<setw(10)<<p->file->maxlength<<setw(10)<<p->file->strat<<setw(10)<<p->file->fileKind<<setw(30)<<asctime(p->file->timeinfo)<<endl;  
  system("pause");
 }
}
图 12 显示用户所有文件

9.修改文件权限

void chmod(char fileName[],char kind[])
{
 UFD *p,*q;
 q=userTable[userID].user;
 for(p=q->next;p!=NULL;p=p->next)
 {
  if(!strcmp(p->file->fileName,fileName))
   break;
 }
 if(p)
 {
     strcpy(p->file->fileKind,kind);
  cout<<"权限修改成功!"<<endl;
  system("pause");
 }
 else
 {
  printf("没有找到该文件,请检查输入的文件名是否正确\n");
  system("pause");
 }
}    
图 13 修改文件权限

10.重名名文件

void fileRen(char fileName[],char rename[])
{

 UFD *p,*q;
 q=userTable[userID].user;
 for(p=q->next;p!=NULL;p=p->next)
 {
  if(!strcmp(p->file->fileName,fileName))
   break;
 }
 if(p)
 {
   strcpy(p->file->fileName,rename);
  cout<<"重命名成功!"<<endl;
  system("pause");
 }
 else
 {
  printf("没有找到该文件,请检查输入的文件名是否正确\n");
  system("pause");
 }
}
图 14 重名名文件

11.盘符显示

void diskShow()
{
 diskNode *p;
 int i=0,unusedDisk=0;
 printf("-------------------------------------------------------------------\n");
 cout<<setw(10)<<"盘块号"<<setw(10)<<"起始地址"<<setw(10)<<"容量(bit)"<<setw(30)<<"是否已被使用(1:是 0:否)"<<endl;
 for(p=diskHead;p!=NULL;p=p->next,i++)
 {
  if(p->useFlag==false) unusedDisk+=p->maxlength;
        cout<<setw(10)<<i<<setw(10)<<p->start<<setw(10)<<p->maxlength<<setw(30)<<p->useFlag<<endl;
 }
    cout<<"磁盘空间总容量:512*1024 bit "<<endl;
 cout<<"已使用:"<<MaxDisk-unusedDisk<<" bit"<<endl;
 cout<<"末使用:"<<unusedDisk<<" bit"<<endl;
 system("pause");
}
图 15 盘符显示

12.删除文件

void delFile(char fileName[])
{
 UFD *p,*q,*temp;
 while(p)
 {
  if(!strcmp(p->file->fileName,fileName)) break;//文件不存在
  else 
  {
   p=p->next;
   q=q->next;
  }
 }
 if(p)
 {
  if(p->file->openFlag!=true)            //先判断是否有进程打开该文件,如果文件没被打开
  {
   temp=p;
   free(temp);
   printf("文件删除成功\n");
   system("pause");
  }
  else
  {
   printf("该文件已被进程打开,删除失败\n");//文件被打开
   system("pause");
  }
 }
 else
 {
  system("pause");
 }
}
图 16 删除文件

13.显示所有用户

 void show_allusers()
{
  if(used==0)
  {
  cout<<"暂无用户!"<<endl;
  }
  else
  {
 cout<<setw(10)<<"用户名"<<setw(10)<<"密码"<<endl;
 for(int i=0;i<used;i++)
 {
 cout<<setw(10)<<userTable[i].userName<<setw(10)<<"******"<<endl;
 }  
 }
    system("pause");
}
图 17 显示所有用户

课程设计体会与软件评价

    通过这次的操作系统课程设计,自己也学到了非常多的新知识,同时也对以前的一些知识复习了一些。拿到课设题目的时候,还是有点懵的,后面选择了文件系统这道题,因为这方面一直都是自己的薄弱地方,想突破一下自己。

    和以往做课程设计一样,拿到题目,首先在网上收集相关的资料,学习别人的思路和见解。然后在根据自己的理解和思考,确定程序所需要实现的功能模块。起初在搭建框架的时候,陷入了困难,因为不知道文件系统到达是怎么实现的?用户是怎么创建目录、文件?对于这个疑惑,咨询了一下同学,之后又去找了文件系统的书看了一下,这才了解文件系统的大体结构。之后就是确定程序的流程,采用哪种输入方法。

    起初想着还是和以前一样,用户选择命令前面的数字,系统根据命令变换确定用户所需要执行的命令。后来想着这和平时使用的Linux系统操作方法完全不一样啊,命令行操作方便又快捷,为何不写一个类似的程序呢?用户直接使用命令操作文件,这样才比较符合用户的操作习惯。为此,自己又拿起C++的课本重新学了一遍文件操作、指针等知识。之后用了一点时间搭建了整个程序的主体框架,然后只需要对每个模块进行填充就好了,这里不是很难。

    在课设中,遇到的问题数不胜数。比如主目录、二级目录的数据结构怎么设计?链表的一些基础操作方式如何选择等等。好在同学们的帮助下,这才完成了文件系统设计。在使用自己设计的这个软件,发现依然存在一些问题,比如在为文件定义操作权限的时候,这里并没有对权限进行用户限制,用户是可以随意定义权限的,这与实际相差比较大。总的来说,这次的收获还是很大的,希望在以后的编程中可以写出更优秀的代码。

    这次的操作系统课程设计,虽然总体上完成了老师所给出的基本功能,添加了一点点新的功能,但是问题还是有很多。比如并没有对文件进行真正的存储,只是利用链表进行了存储,导致一旦程序关闭,用户数据就不见了。

    其实在设计程序的时候也考虑过这个问题,但是对于文件的操作,一直都是自己的痛点,在C++的基础课上,文件这一部分没有学的很好,希望在以后的学习过程中,可以查缺补漏。其次就是程序的优化并没有做的很好,存在很多冗余的地方,代码的优化空间还是很大的。总结这次的程序,做的没有以前的课设那么好,在用户交互性方面还值得改进和提升。

源代码

运行环境:VC 6.0(vs会报错)

下载链接🔗:点击下方“写留言|查看留言”

进入留言板就可以查看

注:

  • 因为有网站老是爬文章,所以把下载链接放在小程序中了
  • 以前编写代码的时候 没有设计到复制文本内容 所以只有手动输入了
  • 若链接失效 麻烦留下言 提醒下 海轰看到会及时更新的

忙了几个月了 没有看到小伙伴们的留言、消息

看到了的基本都发了代码

真的很抱歉 确实有点忙

之后会陆续整理课程设计源代码的

不需要再用竹笋下载了

直接获取就行了

小程序也会比较大的更新

工作量较大 见谅~

写留言|查看留言

浏览 137
1点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
1点赞
评论
收藏
分享

手机扫一扫分享

举报