操作系统课程设计——文件管理系统(C语言版)

发布时间:2024年01月07日

操作系统系列文章

http://t.csdnimg.cn/7XAnU

文章目录

实验一、进程的创建与撤销:http://t.csdnimg.cn/po4V0

实验二、银行家算法:http://t.csdnimg.cn/O5zoF


目录

操作系统系列文章

文章目录

文件管理

一、目的

二、设计内容

三、?设计要求

四、设计思想

1、总体设计思想

2、?结构体FCB

3、创建文件或目录

4、寻找空磁盘存文件

5、删除文件

五、源代码

六、运行结果

七、课设总结:


文件管理

一、目的

????????通过模拟磁盘,完成操作系统的文件管理功能,掌握包括目录结构的管理、外存空间的分配与释放以及空闲空间管理三部分。为写入模拟磁盘的数据文件建立目录,目录可以是单级文件目录、双级文件目录、树形结构目录。在目录中选择某个文件可以将其数据读入模拟内存。

二、设计内容

?1、通过初始化操作建立一个模拟磁盘,在模拟磁盘中保存目录和文件内容。创建该模拟磁盘时可创建初始的根目录内容、文件分配表。

?2、文件目录项(可以采用FCB格式)应包括文件名、类型(目录 or文件)、创建日期、大小、第一个磁盘块块号。

3、目录管理需支持:

  • (1)新建目录:在目录中新建空目录;
  • (3)删除目录:删除空目录
  • (4)为文件建立目录项:一个文件创建成功后,为该文件创建目录项,并将文件和相关信息写入目录;
  • (5)删除文件:删除目录中某个文件,删除其在磁盘中的数据,并删除目录项。如果被删除文件已经读入内存应阻止删除,完成基本的文件保护。

三、?设计要求

1.不同的功能使用不同的函数实现(模块化),对每个函数的功能和调用接口要注释清楚。对程序其它部分也进行必要的注释。

2.对系统进行功能模块分析、画出总流程图和各模块流程图。

3.用户界面要求使用方便、简洁明了、美观大方、格式统一。所有功能可以反复使用,最好使用菜单。

4.通过命令行相应选项能直接进入某个相应菜单选项的功能模块。

5.所有程序需调试通过。

四、设计思想

1、总体设计思想

此文件管理系统主要分为两个模块,一是目录管理,二是文件管理。

具体的模块功能如下:

(1)目录管理:目录管理主要是对目录的操作,包括创建、删除、查看、修改目录名以及切换目录等。

  • ?创建目录:在当前目录下新建空目录,新件目录名不能与同级目录重名,但不同级目录可以重名。
  • 删除目录:在当前目录下删除空目录,如果不是空目录不可以删除。
  • 查看当前目录下的信息:可以查看当前目录的下的目录和文件,展现其相关信息,如名称、类型、创建时间、文件大小等。
  • 修改目录名:在当前目录下可修改目录名称,同理修改后的名称不能与同级目录重名。
  • 切换目录:在当前目录下可切换到上一级目录和下一级目录中。

(2)文件管理:主要是对文件的操作,包括创建、删除、修改文件名、打开、关闭文件以及查看FAT表和位示图等。

  • 创建文件:在当前目录下创建文件,在创建时需要输入名称、文件大小。
  • 删除文件:在当前目录下删除文件,当文件是打开状态则不能删除,必须先将其关闭后才能成功删除文件。
  • 修改文件名:在当前目录下可修改文件名称,同理修改后的名称不能与同级目录下的重名。
  • 查看FAT和位示图:查看文件分配表,即文件具体存储的盘块的位置,查看位示图,即当前盘块的状态。

2、?结构体FCB

????????该文件管理系统设计了一个文件目录项,采用FCB格式,其中包括文件名、类型(目录or文件)、创建时间、大小、第一个盘块号。其中存储目录或文件采用二叉树的模式。FCB结构体定义如下:

typedef struct FCB
{ ? ? ? ? ? ? ? ? ? ? ? //文件或目录控制块
? ? char name[10]; ? ? ?//文件或目录名
? ? int size; ? ? ? ? ? //文件或目录大小,目录大小可设置为 0
? ? char type; ? ? ? ? ?//类型,1 为文件,2 为目录
? ? int first; ? ? ? ? ?//外存起始位置 ?-1被占 -2未被占
? ? char datetime[128]; //日期时间,格式为 yyyymmdd hhmmss
? ? struct FCB *next; ? //下一个兄弟节点,相同父结点的节点称为兄弟结点
? ? struct FCB *child; ?//第一个孩子节点
? ? struct FCB *parent; //父节点
? ? int read = 0; ? ? ? //是否打开,1为打开,0为关闭

} F;

?

3、创建文件或目录

?

4、寻找空磁盘存文件

????????当新建文件时,需要根据文件大小为其分配磁盘空间存储文件。该功能主要是通过findNULL()函数实现的,主要思想如下:

????????首先,通过文件大小f_size计算需要多少个盘块F_SIZE,需要使用向上取整的方式计算,已经规定每个盘块大小为10B,计算方法如下:F_SIZE=(f_size - 1)/10然后利用for循环遍历b[][]位示图数组,找到空闲盘块,将其转换为盘块号 x=i*8+j,并将盘块号x存放在临时数组m[100]中,并修改位示图,b[i][j]=1(为1表示占用,0表示未占用),跳出本次循环,然后在进行第二次循环寻找第2个可用盘块,直到k=F_SIZE,结束最外层循环,已经全部找到可用盘块位置。

????????其次 ,当盘块号全部找到后修改FAT表(-2表示未被占用,-1表示已用,大于0 的数表示磁盘号),FAT表是一个索引表,FAT[i]表示下一个盘块号,i表示该文件的第一个盘块号。

5、删除文件

????????定义全局结构体变量p,指向当前目录,定一个局部结构体变量np,并使np=p。删除文件首先要输入删除文件或目录名name,然后遍历二叉树找到该目录的前一个结点,即np->next->name=name,然后判断np->next是的类型是否为文件,如果是将其删除,并调用updateTable()更新FAT表和位示图。如果都遍历完没有找到,提示用户该文件不存在!

6、切换目录

????????定义全局结构体变量p,指向当前目录,定一个局部结构体变量np,并使np=p,在使得np指向其孩子结点。利用while循环遍历二叉树,寻找到np->name=name, 找到后将np赋给p,使得p指向np.当np==NULL ,提示用户未找到该文件或目录。最后调用updatelujing()函数显示当前路径。

五、源代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
/*
先假设内存大小为64kb,块大小为1K,一个文件或目录最多可以用3个盘块存储
1、先建立位示图,利用随机函数生成*/
// 1为目录,2为文件
void menu();               //菜单
void initdir();            //初始化根目录
void byteCreat();          //创建位示图
void updatelujing();       //更新当前光标所在位置(就是路径)
int updateTable(int, int); //当文件删除时,修改FAT表和修改位示图
int findNULL();            //寻找空位置
void getTime();            //获取时间

void create_Dir(int); //创建目录或者文件
void delDir(char *);  //删除空目录
void printNow();      //显示当前目录下的文件或目录
void delFile(char *); //删除文件
void cdir(char *);    //切换下一级
void byteShow();      //显示位示图
void fatShow();       //显示FATm
void openfile(char);  //打开文件
void closefile(char); //关闭文件

typedef struct FCB
{                       //文件或目录控制块
    char name[10];      //文件或目录名
    int size;           //文件或目录大小,目录大小可设置为 0
    char type;          //类型,1 为文件,2 为目录
    int first;          //外存起始位置  -1被占 -2未被占
    char datetime[128]; //日期时间,格式为 yyyymmdd hhmmss
    struct FCB *next;   //下一个兄弟节点,相同父结点的节点称为兄弟结点
    struct FCB *child;  //第一个孩子节点
    struct FCB *parent; //父节点
    int read = 0;       //是否打开,1为打开,0为关闭

} F;

int COUNT = 0; //文件个数
int F_SIZE;    //一个文件可以占几个盘块
// int F_SIZE_LIST[50]; //每个文件的盘块个数

F *p = NULL;     //全局变量,指向当前目录
int b[100][100]; //位示图数组
int FAT[100];    //文件分配表
// node *head = NULL; //全局变量,?

// 1、获取当前创建时间,利用time函数
void getTime(FCB *f)
{
    time_t t; //时间对象变量
    char buf[128];
    memset(buf, 0, sizeof(buf)); //清空数组

    struct tm *tmp; //时间结构体
    t = time(NULL);
    tmp = localtime(&t);
    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tmp);

    for (int i = 0; i < 128; i++) //存时间
    {
        f->datetime[i] = buf[i];
    }
}
//创建位示图
void byteCreat()
{
    srand((unsigned)time(NULL));
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            b[i][j] = rand() % 2; //随机生成位示图 0表未用,1表已用

            printf("%d ", b[i][j]); //打印出来

            //修改一下把-2表示未用
            if (b[i][j] == 0)
            {
                FAT[i * 8 + j] = -2; //未被占;
            }
            else if (b[i][j] == 1)
            {
                FAT[i * 8 + j] = -1; //-1:被占
            }
        }
        printf("\n");
    }

    printf("\n***FAT表的初始值如下:\n");
    printf("\n");
    for (int i = 0; i < 64; i++)
    {

        printf("%3d ", FAT[i]);
        if (i != 0 && ((i + 1) % 8 == 0))
        {
            printf("\n");
        }
    }
    printf("\n");
}
// 2、寻找空位置
int findNULL()
{
    int a = 0; //哨兵
    int x;     //转化为盘块号
    int m[100];
    for (int k = 0; k < F_SIZE; k++)
    {
        a = 0;
        for (int i = 0; i < 8; i++) //第一行0,一趟就找一个0,而且是最先出现的0.
        {
            for (int j = 0; j < 8; j++)
            {
                if (b[i][j] == 0)
                {
                    x = i * 8 + j; //转化为盘块号
                    m[k] = x;      //存入第一个盘块位置
                    b[i][j] = 1;
                    a = 1;
                    break;
                }
            }
            if (a == 1)
                break; //跳出第二层循环
        }
    }

    printf("\n\n-------找到的盘块位置如下------\n\n");
    for (int k = 0; k < F_SIZE; k++)
    {
        printf("%d,", m[k]);
    }

    //创建FAT表
    for (int k = 0; k < F_SIZE; k++)
    {
        int y = 0;
        y = m[k];          //当k=0时,把第一个盘块号给Y,
        FAT[y] = m[k + 1]; //第盘块Y号指向下一个盘块号,所以FAT[y]的值代表下一个盘块号位置
        printf("\nFAT[y]下一个盘块是:%d\n", FAT[y]);
        //最后一个没有下一个盘块位置
        if (k == F_SIZE - 1)
        {
            FAT[y] = -1; //外存起始位置  -1被占 -2未被占,最后一个没有下一个盘块位置
            printf("\nFAT[y]下一个盘块是:%d\n", FAT[y]);
        }
        //最后一个没有下一个盘块位置
    }
    return m[0];
}

// 3、创建目录
void create_Dir(int a)
{
    char name[10];
    F *np = p;
    printf("请输入目录或文件的名字\n");
    scanf(" %s", name);

    F *f = (F *)malloc(sizeof(F)); //新建空白目录
    strcpy(f->name, name);
    //赋值
    //-------创文件--------
    if (a == 1) // ,1表示文件
    {
        int f_size;
        printf("\n请输入文件大小(单位B):");
        scanf("%d", &f_size);
        f->size = f_size;
        F_SIZE = (f_size - 1) / 10; //向下取整,算个需要多少盘块
        f->read = 0;
        // F_SIZE_LIST[COUNT] = F_SIZE; //将这个文件需要的盘块数存入数组中
        COUNT++;               //文件数加一
        f->type = 1;           //写入类型
        f->first = findNULL(); //找空位置,返回x,x是第一个磁盘号(位置)
        printf("\n----找到的起始位置是:%d\n\n", f->first);
    }

    //----------创目录---------
    if (a == 2) // 2表示目录
    {
        f->type = 2;
        f->first = -2;
        f->size = 0;
    }
    getTime(f);
    f->child = NULL;
    f->next = NULL;
    f->parent = np; // np当前目录
    if (np->child == NULL)
    {
        np->child = f;
    }
    //当前使用用的是链表进行存储文件的,映射成一棵树,
    //在当前目录创建,需要找到一个结点,该结点的兄弟结点为空时,插入,就是在最后插入
    else //进入当前子目录
    {
        np = np->child; //指向第一个目录或文件,假设为F1
        if (a == 2)
        {
            if (np->type == 2) //目录
            {
                //有两个情况,1是建在目录和文件,2是建在目录与目录中(正常情况)
                while (np->next != NULL) //指当前F1的兄弟结点不为空
                {
                    if (np->type == 2 && np->next->type == 1) //新建在目录和文件中间
                    {
                        break;
                    }
                    np = np->next; //指向下一个,继续找兄弟节点直到找到没有兄弟结点的位置,也就是末尾。
                }
                //没有兄弟节点位置,末尾插入,
                f->next = np->next;
                np->next = f;
            }
        }

        else if (a == 1) //文件的,同理
        {
            while (np->next != NULL)
            {
                np = np->next;
            }
            f->next = np->next;
            np->next = f;
        }
    }
}

// 4、更新当前光标所在位置(就是路径)
void updatelujing() //更新当前光标所在位置(就是路径)
{
    F *np = p;     //将np指向当前目录 ,FCB
    F a[100];      //临时存储文件或目录信息结构体数组
    int count = 0; // 局部变量??

    while (np->parent != NULL) //如果父结点不为空,第一次未创建文件或目录时不会执行
    {
        a[count] = *np;  //将当前信息存入数组a中
        np = np->parent; // np从当前位置一直往上找父节点,直到根目录就结束
        count++;         //???
    }
    //输出当前目录前的路径,除了它本身,这样是为了可以输出root\>
    for (int i = count - 1; i > 0; i--)
    {
        printf("%s\\", a[i].name);
    }

    //输出当前目录的名字。
    printf("%s\\", p->name); // p是当前目录,没有创建目录时,p->name为root
    printf(">");             //最后打印出来就是 root\>
}

//初始化根目录
void initdir()
{
    F *f = (F *)malloc(sizeof(F)); //开辟一个FCB,根目录
    //初始化根目录 独立出来
    strcpy(f->name, "root");
    f->type = 2;      // 2表目录
    f->size = 0;      //大小为0
    getTime(f);       //获取创建时的时间
    f->child = NULL;  //孩子结点为空
    f->next = NULL;   //下一个兄弟节点
    f->parent = NULL; //父节点
    f->first = -2;
    p = f; // p指向当前目录,p指向根目录
}

void delDir(char *name) //删除空目录,删除当前目录的一级子目录,且为空目录
{
    int flag = 0;
    F *np = p;
    if (np->child == NULL) //当前目录下的
        printf("无此目录\n");
    else
    {
        np = np->child;
        if (strcmp(np->name, name) == 0 && np->child == NULL) //为第一个,当前的子目录
        {
            p->child = np->next;
            free(np);
            printf("成功删除此目录\n");
            flag = 1;
        }
        else
        {
            while (np->next != NULL) //找到要删除的前一个并且为空文件夹
            {
                if (strcmp(np->next->name, name) == 0 && np->next->child == NULL)
                {
                    np->next = np->next->next; //把当前np的兄弟结点指向要删除的兄弟结点,后一个目录往前移
                    flag = 1;
                    printf("成功删除此目录\n");
                    break;
                }
                np = np->next;
            }
        }
        if (flag == 0)
        {
            printf("删除失败!无当前目录或当前目录不为空\n");
        }
    }
}

//输出当前目录下的文件或目录
void printNow()
{
    F *np = p;
    if (p->child == NULL)
    {
        printf("当前文件夹为空\n");
    }
    else
    {
        np = np->child;
        // printf("%s    <DIR>      .\n", np->parent->datetime);
        printf("%s    <DIR>      ..\n", np->parent->datetime);
        while (np != NULL)
        {
            printf("%s 类型:%d 名字:%s\n", np->datetime, np->type, np->name);
            np = np->next;
        }
    }
}

//删除文件
void delFile(char *name)
{
    int flag = 0;
    F *np = p;
    if (np->child == NULL)
        printf("无此文件\n");
    else
    {
        np = np->child;
        if (strcmp(np->name, name) == 0) //为第一个
        {
            if (np->read == 0)
            {
                printf("\n文件状态%d \n", np->read);
                p->child = np->next;
                printf("\n成功删除此文件\n");
                updateTable(np->first, np->size); //更新fat表
                flag = 1;
            }
            else
            {
                printf("\n文件状态%d \n", np->read);
                flag = 1;
                printf("\n文件已经打开,请关闭再删除!\n");
                printf("删除失败!\n\n");
            }
        }
        else
        {
            while (np->next != NULL)
            {
                if (strcmp(np->next->name, name) == 0) //找到前一个,要删除的
                {
                    if (np->next->read == 0)
                    {
                        printf("\n文件状态%d \n", np->next->read);
                        updateTable(np->next->first, np->next->size); //更新fat表
                        np->next = np->next->next;
                        flag = 1;
                        printf("成功删除此文件\n");
                        break;
                    }
                    else
                    {
                        printf("\n文件状态%d \n", np->next->read);
                        flag = 1;
                        printf("\n文件已经打开,请关闭再删除!\n");
                        printf("删除失败!\n\n");
                    }
                }
                np = np->next;
            }
        }
        if (flag == 0)
        {
            printf("删除失败!无当前目录或当前目录不为空\n");
        }
    }
}

//更新FAT表和位示图
int updateTable(int first, int size) //更新FAT表
{

    int next = first; // 第一个盘号
    int p_count = (size - 1) / 10;
    int m[50]; //临时数组,存该文件的每个盘块号
    //m[0] = next;
    int count = 0;
    //找到所有盘块号,存入m
    int i = next;
    while (1)
    {
        // if (FAT[i] != -2 && FAT[i] != -1) //不为-2

        int j = FAT[i];
        m[count] = i;
        count++;
        i = j;
        if (j == -1)
        {
            break;
        }
    }
    //修改FAT
    for (int i = 0; i < p_count; i++)
    {
        FAT[m[i]] = -2;
    }

    //修改位示图
    for (int i = 0; i < p_count; i++)
    {
        b[m[i] / 8][m[i] % 8] = 0;
    }
    return 0;
}

//
void cdir(char *name) //切换目录下一个目录
{
    F *np = p;
    np = np->child;                  //让np指向当前目录的孩子结点(下一级目录或文件)
    if (strcmp(np->name, name) == 0) //判断两个是否相等
    {
        p = np; //找到并进入,当前目录p就为np
    }
    else
    {
        while (strcmp(np->name, name) != 0)
        {                                    //不等于,就找下一个
            np = np->next;                   //找其
            if (strcmp(np->name, name) == 0) //找到就进入
            {
                p = np; //找到并进入
                break;
            }
            if (np == NULL) //全部遍历完,都没有找到
            {
                printf("未找到此目录");
                break;
            }
        }
    }
}

//显示位示图
void byteShow()
{
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            printf("%d ", b[i][j]);
        }
        printf("\n");
    }
}

void fatShow() //文件配置表
{
    printf("\n");
    printf("\n-------FAT表如下:\n");
    for (int i = 0; i < 64; i++)
    {

        printf("%3d ", FAT[i]);
        if (i != 0 && ((i + 1) % 8 == 0))
        {
            printf("\n");
        }
    }
    printf("\n");
}

void openfile(char *name) //打开文件
{
    F *np = p;
    np = np->child;                  //让np指向当前目录的孩子结点(下一级目录或文件)
    if (strcmp(np->name, name) == 0) //判断两个是否相等
    {
        np->read = 1; //标记状态已读
    }
    else
    {
        while (strcmp(np->name, name) != 0)
        {                                    //不等于,就找下一个
            np = np->next;                   //找其
            if (strcmp(np->name, name) == 0) //找到就进入
            {
                // p = np; //找到并进入
                np->read = 1; //标记状态已打开
                printf("\n文件已经打开!\n");
                break;
            }
            if (np == NULL) //全部遍历完,都没有找到
            {
                printf("未找到此目录");
                break;
            }
        }
    }
}

void closefile(char *name) //关闭文件
{
    F *np = p;
    np = np->child;                                   //让np指向当前目录的孩子结点(下一级目录或文件)
    if (strcmp(np->name, name) == 0 && np->type == 1) //判断两个是否相等,且为文件
    {
        np->read = 0; //标记状态已读
    }
    else
    {
        while (strcmp(np->name, name) != 0)
        {                                                     //不等于,就找下一个
            np = np->next;                                    //找其
            if (strcmp(np->name, name) == 0 && np->type == 1) //找到就进入
            {
                // p = np; //找到并进入
                np->read = 0; //标记状态已关闭
                printf("\n文件已经关闭!\n");
                break;
            }
            if (np == NULL) //全部遍历完,都没有找到
            {
                printf("未找到此目录");
                break;
            }
        }
    }
}

//菜单
void menu()
{

    char choise[10];
    char f_name[10];
    int flag = 1;
    while (flag)
    {
        printf("\n*************文件系统***************************\n");
        printf("             1.md(创建目录)\n");
        printf("             2.rd(删除目录)\n");
        printf("             3.dir(列出当前目录下信息)\n");
        printf("             4.mk(创建文件)\n");
        printf("             5.del(删除文件)\n");
        printf("             6.cd(切换目录)\n");
        printf("             7.cd..(返回上一级)\n");
        printf("             8.fat(展示文件分配表FAT)\n");
        printf("             9.show(展现位示图)\n");
        printf("             10.open(打开文件)\n");
        printf("             11.close(关闭文件)\n");
        printf("*************************************************\n\n");
        do
        {
            //更新当前所在(当前所在路径)*
            updatelujing();
            scanf("%s", &choise);

            //创建目录*
            if (strcmp(choise, "md") == 0)
            {
                create_Dir(2); // 2为目录,1为文件
            }
            //删除空目录*
            else if (strcmp(choise, "rd") == 0)
            {
                //printf("请输入需要删除的文件名\n");
                scanf("%s", f_name);
                delDir(f_name);
            }
            //显示当前目录下目录或文件*
            else if (strcmp(choise, "dir") == 0) //
            {
                printNow();
            }
            //创建文件*
            else if (strcmp(choise, "mk") == 0)
            {
                create_Dir(1); // 1为文件
            }
            //删除文件*
            else if (strcmp(choise, "del") == 0)
            {
                //printf("请输入需要删除的文件名\n");
                scanf("%s", f_name);
                delFile(f_name); //删除文件
            }
            //切换下一级目录*
            else if (strcmp(choise, "cd") == 0)
            {
                //printf("请输入目录名\n");
                scanf(" %s", f_name);
                cdir(f_name);
            }
            //切换上一级*
            else if (strcmp(choise, "cd..") == 0)
            {
                p = p->parent; //直接让当前目录的指针指向父节点。
            }
            //展示FAT*
            else if (strcmp(choise, "fat") == 0)
            {
                fatShow();
            }
            //展示位示图*
            else if (strcmp(choise, "show") == 0)
            {
                byteShow();
            }
            else if (strcmp(choise, "open") == 0) //读文件
            {
                //printf("请输入需要读的文件名\n");
                scanf("%s", f_name);
                openfile(f_name);
            }
            else if (strcmp(choise, "close") == 0) //写文件
            {
                //printf("请输入需要关闭的文件名\n");
                scanf("%s", f_name);
                closefile(f_name);
            }

        } while (flag == 1);
    }
}

int main()
{

    printf("\n------初始化根目录中...\n");
    initdir(); //初始化根目录
    printf("****初始化位示图\n");
    byteCreat(); //创建位示图
    menu();      //菜单
    return 0;
}

六、运行结果

1、进入系统初始界面

2、测试数据

(1)创建目录

测试在根目录root下创建两个子目录11和22,在子目录11中在创建子目录111。结果如下:

(2)删除空目录

测试删除目录,删除目录11,和目录222,只有空目录才能删除。测试结果如下:

(3)切换目录

(4)创建文件

  1. 在根目录下创建qq.txt 文件,大小为32B测试结果如下:

  1. 在11目录下新建文件ww.txt 大小为21B,测试结果如下:

(5)删除文件

测试在11目录下删除已打开的ww.txt文件,文件打开状态不能删除文件,关闭后才能删除。测试结果如下:

(6)打开文件

打开ww.txt文件,测试结果如下:

(7)关闭文件

关闭qq.txt文件,测试结果如下:

七、课设总结:

????????本次课程设计的选题是文件管理,在此次课程设计中收获颇多。不仅加深了对操作系统这门课程的理解,通过实操还将课本上的知识、对文件管理所涉及的思想应用到实际的开发上。在此次设计过程中也遇到了一些问题及其解决方案如下:

(1)最开始新建文件时,是固定了每个文件只能占3个盘块,后来发现这是一个可以改进的缺陷,于是在FCB结构体中在定义了一个代表文件大小的属性size,然后模拟的一个磁盘大小是10B,一共64个磁盘。通过对向上取整根据每个文件大小计算需要多少个盘块,即F_SIZE=(size-1) /10.这样就得到F_SIZE每个文件所需的盘块数。最后利用三重for循环将所需的盘块,每次找到一个空闲磁盘块就结束,寻找第二个时从头开始找。找到并存入临时数组m[100]中。其中在查找空闲磁盘块中也是存在缺陷的,时间复杂度较高。还有改进的空间,可改成找到所有所需的磁盘块在结束,即寻找第二个盘块就无需从头开始。

(2)在新建文件后更改FAT表时也存在一些缺陷。原先设计的FAT表中如果FAT[i]为大于0的数就是代表盘块号,在后续的开发中发现,当需要寻找每个文件存储在哪个盘块时比较麻烦,后来回归课本,发现可以使用索引的方式可以快速的、准确的找到每个文件所占用的盘块号,即FAT[i]表示下一个盘块号,i表示文件的第一个盘块号。

(3)在删除文件后需要更改FAT表及位示图中也遇到一些麻烦。因为FAT[i]表示的含义下一个盘块号,就无法使用简单的遍历FAT表找到就将其修改。因为这个问题想了很久,最终找到了解决方法,具体实现是这样的,先取出该文件的一个盘块号first和文件大小,计算该文件需要多少个盘块记为F_SIZE,利用while循环在循环中定义一个变量j,存FAT[i]的值,即索引的下一个盘块号,i=first即最开始为第一个盘块号,先将i存储在临时数组m[ ]中,然后使i=j,继续进入下一次循环,直到j=-1,( 即FAT[i]=-1表示最后一个磁盘没有索引号了 ),故结束循环.最后利用m数组修改FAT和位示图。


文章来源:https://blog.csdn.net/m0_71233415/article/details/135441668
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。