模拟文件系统课程设计

补上 资源下载地址   微笑


http://download.csdn.net/download/leestar0622/4500162


课程设计的实验文档,简单模拟linux文件系统的结构并作简单实现

实验概述

【实验目的及要求】

通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能及内部实现。

 

 

【实验原理】

1.  通过对课本第四章文件系统的理解,分析了Unix系统的文件系统的实现原理

2.  对linux c提供的文件系统的操作函数的数据结构,函数功能进行分析

3.  将课本P181 图4-35的图进行代码实现

4.  在linux环境下进行实践,熟悉ls –all 列目录,创建目录,linux c编程

【实验环境】

 

Linux Ubuntu

VMware 虚拟机

Window 7 操作系统

Eclipse C/C++ IDE

 

实验内容

【实验方案设计】

   为linux系统设计一个简单的二级文件系统。要求做到以下几点:

  (1)可以实现下列几条命令(至少4条);

                                           

   login        用户登陆

   dir          列文件目录

   create       创建文件

   delete       删除文件

   open         打开文件

   close        关闭文件

   read         读文件

   write        写文件

 

  (2)列目录时要列出文件名、物理地址、保护码和文件长度;

  (3)源文件可以进行读写保护。

【实验过程】(实验步骤、记录、数据、分析)

(1)首先应确定文件系统的数据结构:主目录、子目录及活动文件等。主目录和子目录都以文件的形式存放于磁盘,这样便于查找和修改。

  (2)用户创建的文件,可以编号存储于磁盘上。如file0,file1,file2...并以编号作为物理地址,在目录中进行登记。

本模拟文件系统的自身特点:

  (1)用户不当可以创建普通的文本文件,还可以创建文件夹进行文件的存放分类,理论上基本实现了多级目录的功能,能够迭代的创建文件夹下去,当然数量是有限制的,或者偏离了老师您给的设计要求,不是二级文件系统,是多级文件系统。

  (2)本程序还有很多不足之处,希望老师能够在评阅的过程中给予一定的指出,我会加以改进学习的

 

程序主要构成部分

(详细代码请看压缩包.cpp后缀的文件)

 FileSystem的代码实现包括以下几个部分

1.     磁盘块的定义和实现

因为当创建文件的时候,需要在磁盘申请磁盘块进行存储,而在对linux进行使用的过程中,我查找不到直接操作磁盘并对磁盘块进行申请的api,所以自己进行模拟,而这里,磁盘块就是一个记录着固定大小的数组的数据文件,以此来记录磁盘块的使用情况,

这里参考的是磁盘使用位图来记录磁盘块是否被使用的情况。

 

#define TOTAL_BLOCK 4096
#define BLOCK_UNUSED 4096
 
#define UNDEFIEN 0
 
#define DIRENT_TYPE 1
#define FILE_TYPE 2
 
void initBlock();
 
bool openBlock(unsigned short * block);
 
void saveBlock(unsigned short * block);
 
bool applyBlocks(unsigned short * b,unsigned short * block,int num);
 
bool retrieveBlocks(unsigned short * b,unsigned short * block);
 
bool deleteBlock(unsigned short * b);

 

2.      I节点的定义和实现

I节点在linux中记录着重要的信息,包括文件属性,磁盘块的指针

在这里我也只对i节点进行简单的模拟,i节点的数据结构包括

1)      用户的id

2)      I节点创建的时间

3)      访问i节点文件的时间

4)      I节点修改时间

5)      指向磁盘块的指针,这里通过数组实现,数组的编号对应磁盘块的地址(备注:可进行设置,这里只是简单实现直接指向磁盘块,没有实现大文件的多次间接块,每个磁盘块存储文本文件的时候一个磁盘块可以存放8字节的信息,有四个磁盘块地址,最多可存放32字节的文本信息;而存放目录文件就是用一个磁盘块存放,也就是4个磁盘块地址使用第一个存放目录文件的磁盘块地址。

6)      文件类型

7)      文件保护信息

8)      连接数(这里我是参考了linux文件系统的ls命令,具体没有实现这个功能)

 

#include<time.h>
#define TOTAL_INODE 1024
#define INODE_TO_BLOCK 4   //每个inode可以映射到4个磁盘块
#define FILE_BLOCK_MAX_LENGTH 8  //每个磁盘块存放的文件类型大小为8字节
 
#define INODE_UNUSERD 1024
 
#define WRITE_ONLY 1
#define READ_ONLY 2
#define WRITE_AND_READ 3
 
struct inode
{
       unsigned short file_type;  //文件类型 目录 或者 文件
       unsigned short protection; //保护位 读 写 读写同时
       unsigned int link_num;    //指向该节点到目录项
       unsigned int user_id;   //文件所属用户到id
       unsigned long file_size;    //文件的大小
       unsigned short disk_add[INODE_TO_BLOCK];     //12个磁盘块到地址,每块地址存储的数据到大小是8bytes,支持32bytes的普通文件,还有特定的目录项文件
       time_t access_time;   //文件被最后访问到时间
       time_t modification_time;   //文件最后被修改到时间
       time_t create_time;   //修改原来到结构,改为i节点被确定使用到时间
};
 
void initInode();
 
bool openInode(struct inode * node);
 
void saveInode(struct inode * node);
 
void listInode(struct inode * node);
 
unsigned short createDirentI(struct inode * node,unsigned short * block,struct user * u);
 
unsigned short  createFileI(struct inode * node,unsigned short * block,struct user * u,unsigned long size,unsigned short protection);
 
bool deleteInode(struct inode * node,unsigned short * block,unsigned short index);
 
bool setProtection(struct inode * i,unsigned short p);
 
bool setCreateTime(struct inode * i,time_t time);
 
bool setAccessTime(struct inode * i,time_t time);
 
bool setModificationTime(struct inode * i,time_t time);

3.      目录项的定义和实现

目录项在linux系统的定义相对简单,在作业中我也进行了简化,目录项的数据结构有

1)      目录名  最大支持255字节的文件名

2)      目录对应的i节点编号

3)      目录项的类型

 

定义的代码:

 

#define UNDEFIEN 0
 
#define DIRENT_TYPE 1
#define FILE_TYPE 2
 
#define DIRENT_NAME_LENGTH_MAX 128
#define TOTAL_DIRENT 64
#define DIRENT_UNDEFIEN 64
 
struct dirent
{
       unsigned short inode_num;
       unsigned short dirent_type;
       char dirent_name[DIRENT_NAME_LENGTH_MAX];
};
 
void initRootD();
 
void saveRoot(struct dirent * d);
 
bool createDirentD(struct dirent * allDirents,const char * name,unsigned short inode_num);
 
bool creatFileD(struct dirent * allDirents,const char * name,unsigned short inode_num);
 
bool isDirentEmpty(struct dirent * allDirents,struct inode * node,int index);
 
unsigned short deleteDir(struct dirent * allDirents,int index);
 
void listDirent(struct dirent * allDirents,struct inode * allInodes);
 
bool openRoot(struct dirent * d);
 
struct dirent * openDir(struct dirent * allDirents,int index,struct inode * node);
 
void saveDir(struct dirent * allDirents,struct inode * allInodes);
 
bool closeDir(struct dirent * allDirents,int index,struct inode * node);
 
void createChildD(unsigned short father_inode_num,unsigned short child_inode_num,unsigned short * disk_add);
 
void createChildF(unsigned short * disk_add,char * file_content);
 
void readFile(struct dirent * allDirents,struct inode * node,int index);
 
int checkDir(struct dirent * allDirents,const char * name);
 
bool openDir(struct dirent * allDirents,struct inode * node,int index);


 

4.      用户的定义和实现

因为是二级文件系统,通过对二级文件系统的定义了解到二级文件系统的第一级是用户,用户登录后进入文件系统第二级,第二级就是对文件系统的操作。用户的数据结构包括以下几个数据项

1)      用户id

2)      用户名

3)      用户登录密码

由于时间的关系,对用户没有进行过多的设置,创建用户后没有提供修改用户账户密码的功能。。。。。。

 

#define TOTAL_USER 32     //该文件系统允许到最大用户数目
#define USER_UNDEFINE 32
 
#define USER_NAME_MAX_LENGTH 32  //用户名到最大长度
#define USER_PASSWORD_MAX_LENGTH 16   //密码到最大长度
 
#define SUPERUSER 0
 
struct user      
{
       unsigned int user_id;
       char user_name[USER_NAME_MAX_LENGTH];
       char user_password[USER_PASSWORD_MAX_LENGTH];
};
 
int checkUser(struct user * allUsers,const char * name);
 
struct user * login(struct user * allUsers,const char * name,const char * password);
 
bool createUser(struct user * allUsers,const char * name,const char * password);
 
bool deleteUser(struct user * allUsers,struct user * u);
 
void initUser();
 
bool openUser(struct user * u);
 
void listUser(struct user * u);
 
void saveUser(struct user * u);

 

5.      主程序的实现

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include"user.h"
#include"dirent.h"
#include"block.h"
#include"inode.h"
 
int main(int argc, char * *argv) {
       if (0) {
              initUser();
              initBlock();
              initRootD();
              initInode();
       }
 
       struct user allUsers[TOTAL_USER];
       struct inode allInodes[TOTAL_INODE];
       struct dirent allDirents[TOTAL_DIRENT];
       unsigned short allBlocks[TOTAL_BLOCK];
 
       struct user * nowUser;
 
       int choise;
 
       bool controler = true;
 
       char name[USER_NAME_MAX_LENGTH];
       char password[USER_PASSWORD_MAX_LENGTH];
       char dirent_name[DIRENT_NAME_LENGTH_MAX];
       char file_name[DIRENT_NAME_LENGTH_MAX];
       char file_content[INODE_TO_BLOCK * FILE_BLOCK_MAX_LENGTH];
 
       printf("---欢迎使用Lee制作的模拟文件系统---\n"
                     "本文件系统又命名为YY文件系统\n");
 
       //登录和注册的循环
       while (controler) {
 
              if (!openUser(allUsers)) {
                     exit(1);
              }
 
              printf("请选择\n1: 老用户登录\t 2: 新用户注册\t 3:退出\n");
              scanf("%d", &choise);
              printf("你的输入是:%d\n", choise);
 
              switch (choise) {
              case 1:
                     printf("欢迎你,老用户\n");
                     printf("请输入用户名:\n");
                     scanf("%s", name);
                     printf("请输入密码:\n");
                     scanf("%s", password);
                     nowUser = login(allUsers, name, password);
                     if (nowUser == NULL) {
                            printf("你输入的用户名或密码有错误\n");
                            continue;
                     } else {
                            if (!openRoot(allDirents)) {
                                   printf("读取根目录的时候出错,请重新登录\n");
                                   continue;
                            }
                            printf("你已经成功登录到Lee到文件系统\n");
                            //进入文件系统后的循环
                            while (allDirents != NULL && openInode(allInodes)
                                          && openBlock(allBlocks)) {
                                   printf("%s@Lee:/\n", nowUser->user_name);
                                   listDirent(allDirents, allInodes);
                                   if (allDirents[0].inode_num == allDirents[1].inode_num) {
                                          printf("请选择\n"
                                                        "1: 创建一个目录\t 2: 进入一个目录\t 3:删除一个目录\n"
                                                        "4:创建一个文件\t 5:打开一个文件\t 6:删除一个文件\n"
                                                        "7:退出\n");
                                   } else {
                                          printf("请选择\n"
                                                        "1:创建一个目录\t 2:进入一个目录\t 3:删除一个目录\n"
                                                        "4:创建一个文件\t 5:打开一个文件\t 6:删除一个文件\n"
                                                        "7:返回上一级目录\n");
                                   }
                                   int action;
                                   scanf("%d", &action);
 
                                   unsigned short inode_num; //获取分配到到inode的序号
                                   unsigned short protection; //设置保护位
                                   unsigned short inode_i; //inode到序号
                                   int dir_i; //目录项序号
                                   unsigned short block_d[INODE_TO_BLOCK]; //删除的block的块序列
 
                                   switch (action) {
                                   case 1:
                                          printf("请输入目录名:\n");
                                          scanf("%s", dirent_name);
                                          if (checkDir(allDirents, dirent_name) != DIRENT_UNDEFIEN) {
                                                 printf("你输入到目录名重复,请重新输入!!\n");
                                                 continue;
                                          }
                                          inode_num = createDirentI(allInodes, allBlocks,
                                                        nowUser);
                                          if (inode_num != INODE_UNUSERD) {
                                                 if (!createDirentD(allDirents, dirent_name,
                                                               inode_num)) {
                                                        printf("创建目录项dirent到时候发生ERROR");
                                                        exit(1);
                                                 } else {
                                                        createChildD(allDirents[0].inode_num, inode_num,
                                                                      allInodes[inode_num].disk_add);
                                                        saveBlock(allBlocks);
                                                        saveInode(allInodes);
                                                        saveDir(allDirents, allInodes);
                                                        printf("成功创建了一个目录\n");
                                                 }
                                          } else {
                                                 printf("分配INODE的时候发生ERROR");
                                                 exit(1);
                                          }
                                          break;
                                   case 2:
                                          printf("请输入目录名:\n");
                                          scanf("%s", dirent_name);
                                          dir_i = checkDir(allDirents, dirent_name);
                                          if (dir_i == DIRENT_UNDEFIEN) {
                                                 printf("你输入到目录名有误,请重新输入!!\n");
                                                 continue;
                                          }
                                          if (!openDir(allDirents, allInodes, dir_i)) {
                                                 printf("打开目录的时候出错,请重新尝试!!\n");
                                                 continue;
                                          }
                                          break;
                                   case 3:
                                          printf("请输入要删除的目录名:\n");
                                          scanf("%s", dirent_name);
                                          dir_i = checkDir(allDirents, dirent_name);
                                          if (dir_i == DIRENT_UNDEFIEN) {
                                                 printf("你输入到目录名有误,请重新输入!!\n");
                                                 continue;
                                          }
                                          if (!isDirentEmpty(allDirents, allInodes, dir_i)) {
                                                 printf("该目录下面有子文件或者子目录,请谨慎删除!!\n");
                                                 continue;
                                          } else {
                                                 inode_i = deleteDir(allDirents, dir_i);
                                                 if (inode_i != INODE_UNUSERD) {
                                                        if (deleteInode(allInodes, block_d, inode_i)) {
                                                               if (deleteBlock(block_d)) {
                                                                     if (retrieveBlocks(block_d,
                                                                                    allBlocks)) {
                                                                             saveBlock(allBlocks);
                                                                             saveInode(allInodes);
                                                                             saveDir(allDirents, allInodes);
                                                                            printf("成功删除了该文件!!\n");
                                                                      }else {
                                                                            printf("重置该文件的磁盘块配置文件出错!!\n");
                                                                      }
                                                               } else {
                                                                     printf("删除该文件的block出错!!\n");
                                                               }
                                                        }
                                                 } else {
                                                        printf("删除该文件的dirent出错!!\n");
                                                 }
                                          }
                                          break;
                                   case 4:
                                          printf("请输入文件名:\n");
                                          scanf("%s", file_name);
                                          if (checkDir(allDirents, file_name) != DIRENT_UNDEFIEN) {
                                                 printf("你输入到目录名重复,请重新输入!!\n");
                                                 continue;
                                          }
                                          printf("请输入文件的内容:\n");
                                          scanf("%s", file_content);
                                          printf("请设置文件保护信息\n 1:只读\t2:只写\t3:读和写\n");
                                          protection = 0; //设置保护位
                                          scanf("%hu", &protection);
//                                        printf("%hu\n", protection);
                                          inode_num = createFileI(allInodes, allBlocks, nowUser,
                                                        strlen(file_content), protection);
                                          printf("%d\n", inode_num);
                                          if (inode_num != INODE_UNUSERD) {
                                                 if (!creatFileD(allDirents, file_name, inode_num)) {
                                                        printf("创建目录项dirent到时候发生ERROR");
                                                        exit(1);
                                                 } else {
                                                        createChildF(allInodes[inode_num].disk_add,
                                                                      file_content);
                                                        saveBlock(allBlocks);
                                                        saveInode(allInodes);
                                                        saveDir(allDirents, allInodes);
                                                        printf("成功创建了一个文件\n");
                                                 }
                                          } else {
                                                 printf("分配INODE的时候发生ERROR");
                                                 exit(1);
                                          }
                                          break;
                                   case 5:
                                          printf("请输入要读取的文件名:\n");
                                          scanf("%s", file_name);
                                          dir_i = checkDir(allDirents, file_name);
                                          if (dir_i == DIRENT_UNDEFIEN) {
                                                 printf("你输入的文件名有误,请重新操作!!\n");
                                                 continue;
                                          }
                                          readFile(allDirents, allInodes, dir_i);
                                          printf("是否对文件进行读写保护位设置\n"
                                                        "请选择\n1: 是\t 2: 否并且退出\n");
                                          int operation;
                                          scanf("%d", &operation);
                                          if (operation == 1) {
                                                 printf("请设置文件保护信息\n 1:只写\t2:只读\t3:读和写\n");
                                                 protection = 0; //设置保护位
                                                 scanf("%hu", &protection);
                                                 if(setProtection(&allInodes[allDirents[dir_i].inode_num],protection)){
                                                        saveInode(allInodes);
                                                        printf("请设置文件保护信息成功\n");
                                                 }else{
                                                        printf("请设置文件保护信息失败\n");
                                                 }
                                          }
                                          break;
                                   case 6:
                                          printf("请输入要删除的文件名:\n");
                                          scanf("%s", file_name);
                                          dir_i = checkDir(allDirents, file_name);
                                          if (dir_i == DIRENT_UNDEFIEN) {
                                                 printf("你输入的文件名有误,请重新操作!!\n");
                                                 continue;
                                          }
                                          inode_i = deleteDir(allDirents, dir_i);
                                          if (inode_i != INODE_UNUSERD) {
                                                 if (deleteInode(allInodes, block_d, inode_i)) {
                                                        if (deleteBlock(block_d)) {
                                                               if (retrieveBlocks(block_d, allBlocks)) {
                                                                      saveBlock(allBlocks);
                                                                      saveInode(allInodes);
                                                                      saveDir(allDirents, allInodes);
                                                                     printf("成功删除了该文件!!\n");
                                                               } else {
                                                                     printf("重置该文件的磁盘块配置文件出错!!\n");
                                                               }
                                                        } else {
                                                               printf("删除该文件的block出错!!\n");
                                                        }
                                                 }
                                          } else {
                                                 printf("删除该文件的dirent出错!!\n");
                                          }
                                          break;
                                   case 7:
                                          if (allDirents[0].inode_num
                                                        == allDirents[1].inode_num) {
                                                 //Do nothing
                                                 printf("---欢迎你再次使用YY文件系统!---\n");
                                                 exit(1);
                                          } else {
                                                 dir_i = checkDir(allDirents, ".."); //其实就是重复第二部,打开“..”文件夹
                                                 if (dir_i == DIRENT_UNDEFIEN) {
                                                        printf("你输入到目录名有误,请重新输入!!\n");
                                                        continue;
                                                 }
                                                 if (!openDir(allDirents, allInodes, dir_i)) {
                                                        printf("打开目录的时候出错,请重新尝试!!\n");
                                                        continue;
                                                 }
                                          }
                                          break;
                                   default:
                                          printf("你的选择有错误,请重新选择!\n");
                                          break;
                                   }
                            }
                            printf("读取系统目录出错,请重新登录尝试\n");
                            continue;
                     }
                     break;
              case 2:
                     printf("欢迎你,老用户\n");
                     printf("请输入用户名:\n");
                     scanf("%s", name);
                     while (checkUser(allUsers, name) != USER_UNDEFINE) {
                            printf("你输入到用户名已被注册,请重新输入\n");
                            scanf("%s", name);
                     }
                     printf("请输入密码:\n");
                     scanf("%s", password);
                     if (!createUser(allUsers, name, password)) {
                            printf("注册的过程发生错误,请重新选择\n");
                     } else {
                            saveUser(allUsers);
                            printf("注册成功,请进行登录或其他操作!\n");
                     }
                     break;
              case 3:
                     controler = false;
                     printf("已经为你退出系统!\n");
                     break;
              default:
                     printf("你的选择有错误,请重新选择!\n");
                     break;
              }
       }
 
}


【运行结果】

截图:(截图省略)

1.登录注册

2.用户注册

3.用户登录

4.进入文件系统后的功能选择

5.进入一个目录

6.在目录下创建目录(目录名可以包含空格)

7.在目录下创建一个文本文件(文件名可以包含空格)

8.打开一个文本文件

9.对文件进行保护位设置

10.            设置为只写之后就不能读取了

11.            删除文本文件

12.            删除一个目录

13.            非根目录可以返回上一级目录

14.            根目录可以退出程序

15. 同名检查,输入同名文件将会被拒绝

16. 访问权限出错

17. 访问文件类型出错

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值