操作系统实验八-文件结构

操作系统第八次实验

个人博客地址

文件结构

一、实验内容

  1. 把文件的逻辑结构转换成存储结构
  2. 设计便于顺序存取和直接存取的文件存储结构。

二、实验目的

  • 研究用户概念中的信息组织方式
  • 理解文件的逻辑结构、存取结构、存取方式之间的联系
  • 模拟设计文件的存储结构

三、实验题目

第一题:

模拟设计MS-DOS操作系统中磁盘文件的存储结构。

  1. 当用户对记录式文件采用顺序存以方式时,用户总是依次地访问一个个逻辑记录,即当访问了第i个记录后,下次总是访问第i+1个记录。所以,当用户采用顺序存取方式访问文件时,只要给出访问要求(读或写)而无需再指出要访问的记录号。

  2. 采用链接文件结构,只有读出一个物理块信息后才能从链接字中得知下一个物理块号。所以,当用户要在文件中插入一些信息时,文件系统必须多次地请求启动磁盘读出信息才能做插入工作。

    MS-DOS操作系统对链接文件结构作了改进,它是把所有的链接指针集中在一起,存放在文件定位表FAT中。查找链接字时不必读出物理块信息可直接从FAT中得到。

  • 其设计思想是:
    假定磁盘上共有N个物理块可供使用,FAT就有N项,初始化时为全“0”,表示对应的物理块均可使用,当要存放文件时,从FAT中寻找为“0”的项,其对应的物理块用来存放文件信息,把文件的链接指针(指出物理块号)登记在FAT中,文件第一块块号登记在文件目录中。

image-20211217135713687

  1. 假定磁盘存储空间共有32个物理块,模拟设计文件定位表FAT。文件定位表可以用一个一维数组FAT[031]来定义,其中一个元素与一个物理块对应。当FAT[i]=0时,表示第i块为空闲块;当FAT[i]=FFF时,表示链接文件到第i块结束;当在0~FFF时,其值指示链接文件中下一个物理块号。
  2. 每个物理块只能存放一个逻辑记录,设计一个程序把文件的逻辑结构模拟转换成MS-DOS的链接结构。
  • 要求保存一个已经在1 1主存中的文件时,给出文件名和文件的逻辑记录长度及个数,对一个已经保存的文件,允许用户插入新记录。用键盘输入来模拟用户的要求,输入信息为:
    “存” 文件名 逻辑记录长度 逻辑记录个数“插入” 文件名 逻辑记录号
  • 模拟程序的算法如下图所示:

image-20211217135808878

  1. 假设系统中已经有两个链接文件,其链接情况由FAT表指出(链接情况学生自定),现又要保存一个新文件,然后对已保存的文件插入一个新记录。运行你所设计的程序,观察其结果。

第二题:

模拟便于直接存取的索引文件结构

  1. 索引文件像链接文件一样,文件的逻辑记录信息可存放在非连续的磁盘存储空间中。但这些存放逻辑记录的存储空间不是按链表的形式链接在一起的,而是采用索引表来指出逻辑记录存放的物理位置。

  2. 文件目录与索引表的关系如下图所示:

    image-20211219192945145

  3. 建立索引文件的过程是:寻找一些空闲物理块;逻辑记录存入这些物理块中;把逻辑记录与物理块的对应关系登记在索引表中。

思考题:

  1. 链表文件结构和索引文件结构各自的优缺点是什么?
  2. 当文件较大时,使得索引表也较大,如果索引表的大小超过了一个物理块,如何进行索引表的存取?

四、实验设计与过程

第一题:MS-DOS磁盘文件存储结构

数据结构和符号说明
//文件定位表 fat
int fat[32];
char phy_file[32];
//主存剩余块的数量
int leftblocks = 32;
//文件目录
struct FD
{
    string name[32];
    //文件起始块号
    int start[32];
    //每个文件逻辑长度
    int filelength[32];
    //文件数量
    int filenum;
} fd;
函数说明

一个存文件函数和一个插入文件函数,模拟链表实现。

//初始化函数,重置 fat
void init()
//存文件操作
void save()
//插入文件操作
void insert()
源代码
// MS-DOS 磁盘文件存储结构
#include <bits/stdc++.h>
using namespace std;
//文件定位表 fat
int fat[32];
char phy_file[32];
//主存剩余块的数量
int leftblocks = 32;
//文件目录
struct FD
{
    string name[32];
    //文件起始块号
    int start[32];
    //文件数量
    int filelength[32];
    int filenum;
} fd;

//初始化函数,重置 fat
void init()
{
    for (int i = 0; i < 32; i++)
        fat[i] = 0;
    //将第一位设置为 FDF
    fat[0] = -2;
    //将第二位设置成所有文件的结束 FFF
    fat[1] = -1;
    leftblocks -= 2;
    fd.filenum = 0;
    // cout << fd.name << endl;
    fd.name[++fd.filenum] = "AB";
    // cout << fd.name[fd.filenum] << endl;
    fd.start[fd.filenum] = 2;
    fat[2] = 5; //初始化第一个文件
    fat[5] = 8;
    fat[8] = 11;
    fat[11] = 18;
    fat[18] = 24;
    fat[24] = 1;
    fd.filelength[fd.filenum] = 6;

    fd.name[++fd.filenum] = "B"; //初始化第二个文件
    fd.start[fd.filenum] = 6;
    fat[6] = 9;
    fat[9] = 14;
    fat[14] = 19;
    fat[19] = 22;
    fat[22] = 28;
    fat[28] = 30;
    fat[30] = 1;
    fd.filelength[fd.filenum] = 7;
}

//寻找相同文件名的条目
//找到就返回在文件目录中的索引
int FindFile(string filename)
{
    for (int i = 1; i <= fd.filenum; i++)
        if (fd.name[i] == filename)
            return i;
    return 0;
}

//存文件操作
void save()
{
    string filename;
    cout << "请输入文件名: ";
    cin >> filename;
    //首先寻找是不是有同名的文件
    //如果有则不能重复插入
    int num;
    cout << "请输入逻辑记录长度: ";
    cin >> num;
    if (FindFile(filename) != 0)
    {
        cout << "********存在同名文件,存操作执行失败!********" << endl;
        return;
    }
    //检查内存剩余的空间是不是够存储
    if (num > leftblocks)
    {
        cout << "********存储的文件过大,无法存储!********" << endl;
        return;
    }
    //记录文件名称
    fd.name[++fd.filenum] = filename;
    int pos = 0, lastpos;
    //找 num 个空的内存块来存储,同时更新索引
    for (int i = 1; i <= num; i++)
    {
        //找到一个空的位置
        while (fat[pos] != 0)
            pos = (pos + 1) % 32;
        //如果是文件的起始块号则直接存储下一个块的索引
        if (i == 1)
            fd.start[fd.filenum] = pos;
        //不是起始块则将上一个块的索引设置成当前的地址
        else
            fat[lastpos] = pos;
        //记录当前地址,实际的复制内容由下一个块的地址决定
        lastpos = pos;
        //从下一个块开始找,空出当前地址留待使用
        pos++;
        //剩余的块少一个
        leftblocks--;
    }
    //将文件的结尾执行统一的结束符 FFF
    fat[lastpos] = 1;
    cout << "********文件存储成功!********" << endl;
}

//插入文件操作
void insert()
{
    string filename;
    cout << "请输入文件名:";
    cin >> filename;
    //首先查找文件目录中是否有这个文件
    //如果有这个文件则记录在文件目录中的索引
    int pos = FindFile(filename);
    //如果没有这个文件则插入不能完成
    if (pos == 0)
    {
        cout << "********不存在该文件,插入失败!********" << endl;
        return;
    }
    //将这个块插入到文件的第 num 个位置
    int num;
    cout << "请输入要插入的文件逻辑位置:";
    cin >> num;
    //判断是否有空间存储这个插入的块
    if (leftblocks == 0)
    {
        cout << "********无空闲块,插入失败!********" << endl;
        return;
    }
    //找一个空闲的位置来存放要插入的块
    int p = 1;
    while (fat[p] != 0)
        p++;
    //如果要在第一个位置插入,则更新起始块号
    if (num == 1)
    {
        fat[p] = fd.start[pos];
        fd.start[pos] = p;
    }
    //不是在第一个位置插入
    else if (num >= 2)
    {
        //找到要插入位置的前一个块号
        int temp = fd.start[pos];
        for (int i = 1; i < num - 1; i++)
            temp = fat[temp];
        //将新的位置的下一个索引指向原来的下一个块
        fat[p] = fat[temp];
        //将上一个块的下一个索引指向新的位置,完成插入
        fat[temp] = p;
    }
    //更新剩余的内存块
    leftblocks--;
    fd.filelength[pos]++;
    cout << "********插入文件块成功!********" << endl;
}

//输出文件目录和 fat
void info()
{
    printf("|-------------------------------|\n");
    printf("|-----------文件目录------------|\n");
    printf("|-------------------------------|\n");
    printf("|  文件名   起始位置  逻辑长度  |\n");
    for (int i = 1; i <= fd.filenum; i++)
        printf("|  %6s  %8d  %9d  |\n", fd.name[i].c_str(), fd.start[i], fd.filelength[i]);
    printf("|-------------------------------|\n");
    printf("\n|--------------------|\n");
    printf("|---文件定位表(fat)--|\n");
    printf("|--------------------|\n");
    printf("|    索引    内容    |\n");
    printf("|      0      FDF    |\n");
    printf("|      1      FFF    |\n");
    for (int i = 2; i < 32; i++)
        printf("|   %4d    %4d     |\n", i, fat[i]);
    printf("|--------------------|\n\n");
}

//功能选择清单
void choicelist()
{
    cout << "|====================================================================|" << endl;
    cout << "|-----------------------MS-DOS磁盘文件存储管理菜单-------------------|" << endl;
    cout << "|                      1.向fat中存储一个文件:                        |" << endl;
    cout << "|                      2.向fat中的文件插入数据:                      |" << endl;
    cout << "|                      3.输出当前文件目录以及fat信息:                |" << endl;
    cout << "|                      4.结束操作,退出系统:                         |" << endl;
    cout << "|====================================================================|" << endl;
}

int main()
{
    init();
    int order;
    while (1)
    {
        //通过字符串输入来选择想要测试的功能
        choicelist();
        cout << "请输入你要执行的操作的编号: ";
        cin >> order;
        switch (order)
        {
        //存 一个文件
        case 1:
            save();
            break;
        //在指定的文件中的特定位置插入一个块
        case 2:
            insert();
            break;
        //显示当前的系统信息
        case 3:
            info();
            break;
        //测试结束退出系统3
        case 4:
            cout << "系统结束" << endl;
            exit(0);
            break;
        //输入指令不合法
        default:
            cout << "指令输入错误" << endl;
        }
    }
    return 0;
}
程序初值和运行结果

初态

image-20211217140649270

保存新文件

image-20211217140757616

对新保存的文件进行插入

image-20211217140850377

第二题:索引文件存储结构

数据结构和符号说明

相比于上一题,增加了三个数据结构,分别是索引表、文件目录表、用户表

同时因为其结构是名称和地址的对应关系,故采用了stl数据结构中的map来反映映射关系。

struct Indextab //索引表
{
    int tab[32];
    int length = 0;
};

struct Filetab//文件目录表
{
    map<string, Indextab> filetab;
};
map<string, Filetab> usertab;//用户表
函数说明

相比于上一题,改动之处在于增加了一个是文件结构改变成索引结构的函数。

函数思路为首先输入用户名,然后依次要求用户输入属于自己的文件,将其加入该用户的文件表中。

void change_to_index()
{   //打印当前文件目录
    printf("当前文件目录:\n");
    printf("|-------------------------------|\n");
    printf("|-----------文件目录------------|\n");
    printf("|-------------------------------|\n");
    printf("|  文件名   起始位置  逻辑长度  |\n");
    for (int i = 1; i <= fd.filenum; i++)
        printf("|  %6s  %8d  %9d  |\n", fd.name[i].c_str(), fd.start[i], fd.filelength[i]);
    printf("|-------------------------------|\n");
    while (1)
    {
        printf("请输入用户名,按q退出\n");
        string name;
        cin >> name;
        if (name == "q")
            break;
        else
        {
            while (1)
            {
                printf("请输入当前用户的文件名,按q退出\n");
                string file;
                cin >> file;
                if (file == "q")
                    break;
                else
                {
                    int t = FindFile(file);
                    if (!t)
                    {
                        printf("不存在该文件,请重新输入文件名:");
                        continue;
                    }
                    else
                    {
                        usertab[name].filetab[file].length = 0;//初始化用户文件表记录数
                        int cpos = fd.start[t];
                        for (int i = 0; i < fd.filelength[t]; i++)
                        {
                            usertab[name].filetab[file].tab[i] = cpos;//记录物理块号
                            cpos = fat[cpos];//到下一个物理块
                            usertab[name].filetab[file].length++;//记录数加一
                        }
                    }
                }
            }
        }
    }
}
源代码
// MS-DOS 磁盘文件存储结构
#include <bits/stdc++.h>
using namespace std;
#define FDF -1
#define FFF -2
//文件定位表 fat
int fat[32];
//主存剩余块的数量
int leftblocks = 32;
//文件目录
struct FD
{
    string name[32];
    //文件起始块号
    int start[32];
    //文件数量
    int filelength[32];
    int filenum;
} fd;

struct Indextab //索引表
{
    int tab[32];
    int length = 0;
};

struct Filetab//文件目录表
{
    map<string, Indextab> filetab;
};
map<string, Filetab> usertab;//用户表

//初始化函数,重置 fat
void init()
{
    for (int i = 0; i < 32; i++)
        fat[i] = 0;
    //将第一位设置为 FDF
    fat[0] = -2;
    //将第二位设置成所有文件的结束 FFF
    fat[1] = -1;
    leftblocks -= 2;
    fd.filenum = 0;
    // cout << fd.name << endl;
    fd.name[++fd.filenum] = 'A';
    // cout << fd.name[fd.filenum] << endl;
    fd.start[fd.filenum] = 2;
    fat[2] = 5; //初始化第一个文件
    fat[5] = 8;
    fat[8] = 11;
    fat[11] = 18;
    fat[18] = 24;
    fat[24] = FFF;
    fd.filelength[fd.filenum] = 6;

    fd.name[++fd.filenum] = 'B'; //初始化第二个文件
    fd.start[fd.filenum] = 6;
    fat[6] = 9;
    fat[9] = 14;
    fat[14] = 19;
    fat[19] = 22;
    fat[22] = 28;
    fat[28] = 30;
    fat[30] = FFF;
    fd.filelength[fd.filenum] = 7;
}

//寻找相同文件名的条目
//找到就返回在文件目录中的索引
int FindFile(string filename)
{
    for (int i = 1; i <= fd.filenum; i++)
        if (fd.name[i] == filename)
            return i;
    return 0;
}
/* int finduser(string name)
{
    map<string, Filetab>::iterator iter;
    iter = usertab.find(name);
    if (iter == usertab.end())
        return 0;
    else
        return 1;
} */
void save()
{
    string filename;
    cout << "请输入文件名: ";
    cin >> filename;
    //首先寻找是不是有同名的文件
    //如果有则不能重复插入
    if (FindFile(filename) != 0)
    {
        cout << "********存在同名文件,存操作执行失败!********" << endl;
        return;
    }
    int num;
    cout << "请输入逻辑记录长度: ";
    cin >> num;
    //检查内存剩余的空间是不是够存储

    if (num > leftblocks)
    {
        cout << "********存储的文件过大,无法存储!********" << endl;
        return;
    }
    //记录文件名称
    fd.name[++fd.filenum] = filename;
    fd.filelength[fd.filenum] = num;
    int pos = 0, lastpos;
    //找 num 个空的内存块来存储,同时更新索引
    for (int i = 1; i <= num; i++)
    {
        //找到一个空的位置
        while (fat[pos] != 0)
            pos = (pos + 1) % 32;
        //如果是文件的起始块号则直接存储下一个块的索引
        if (i == 1)
            fd.start[fd.filenum] = pos;
        //不是起始块则将上一个块的索引设置成当前的地址
        else
            fat[lastpos] = pos;
        //记录当前地址,实际的复制内容由下一个块的地址决定
        lastpos = pos;
        //从下一个块开始找,空出当前地址留待使用
        pos++;
        //剩余的块少一个
        leftblocks--;
    }
    //将文件的结尾执行统一的结束符 FFF
    fat[lastpos] = FFF;
    cout << "********文件存储成功!********" << endl;
}

//插入文件操作
void insert()
{
    string filename;
    cout << "请输入文件名:";
    cin >> filename;
    //首先查找文件目录中是否有这个文件
    //如果有这个文件则记录在文件目录中的索引
    int pos = FindFile(filename);
    //如果没有这个文件则插入不能完成
    if (pos == 0)
    {
        cout << "********不存在该文件,插入失败!********" << endl;
        return;
    }
    //将这个块插入到文件的第 num 个位置
    int num;
    cout << "请输入要插入的文件逻辑位置:";
    cin >> num;
    //判断是否有空间存储这个插入的块
    if (leftblocks == 0)
    {
        cout << "********无空闲块,插入失败!********" << endl;
        return;
    }
    //找一个空闲的位置来存放要插入的块
    int p = 1;
    while (fat[p] != 0)
        p++;
    //如果要在第一个位置插入,则更新起始块号
    if (num == 1)
    {
        fat[p] = fd.start[pos];
        fd.start[pos] = p;
    }
    //不是在第一个位置插入
    else if (num >= 2)
    {
        //找到要插入位置的前一个块号
        int temp = fd.start[pos];
        for (int i = 1; i < num - 1; i++)
            temp = fat[temp];
        //将新的位置的下一个索引指向原来的下一个块
        fat[p] = fat[temp];
        //将上一个块的下一个索引指向新的位置,完成插入
        fat[temp] = p;
    }
    //更新剩余的内存块
    leftblocks--;
    fd.filelength[pos]++;
    cout << "********插入文件块成功!********" << endl;
}
void change_to_index()
{   //打印当前文件目录
    printf("当前文件目录:\n");
    printf("|-------------------------------|\n");
    printf("|-----------文件目录------------|\n");
    printf("|-------------------------------|\n");
    printf("|  文件名   起始位置  逻辑长度  |\n");
    for (int i = 1; i <= fd.filenum; i++)
        printf("|  %6s  %8d  %9d  |\n", fd.name[i].c_str(), fd.start[i], fd.filelength[i]);
    printf("|-------------------------------|\n");
    while (1)
    {
        printf("请输入用户名,按q退出\n");
        string name;
        cin >> name;
        if (name == "q")
            break;
        else
        {
            while (1)
            {
                printf("请输入当前用户的文件名,按q退出\n");
                string file;
                cin >> file;
                if (file == "q")
                    break;
                else
                {
                    int t = FindFile(file);
                    if (!t)
                    {
                        printf("不存在该文件,请重新输入文件名:");
                        continue;
                    }
                    else
                    {
                        usertab[name].filetab[file].length = 0;//初始化用户文件表记录数
                        int cpos = fd.start[t];
                        for (int i = 0; i < fd.filelength[t]; i++)
                        {
                            usertab[name].filetab[file].tab[i] = cpos;//记录物理块号
                            cpos = fat[cpos];//到下一个物理块
                            usertab[name].filetab[file].length++;//记录数加一
                        }
                    }
                }
            }
        }
    }
}
void info_change_after()
{
    map<string, Filetab>::iterator it;
    map<string, Indextab>::iterator fileit;
    printf("**********************************\n");
    // fflush(stdin);
    for (it = usertab.begin(); it != usertab.end(); it++)
    {
        // fflush(stdin); //重写操作。目的是清除缓存。
        printf("\n|-----------------------|\n");
        printf("|----用户%4s的索引表---|\n", it->first.c_str());

        printf("|-----------------------|\n");
        for (fileit = usertab[it->first].filetab.begin(); fileit != usertab[it->first].filetab.end(); fileit++)
        {
            printf("|--------文件名:%s-------|\n", fileit->first.c_str());
            printf("|   记录号   物理块号   |\n");
            for (int j = 0; j < fileit->second.length; j++)
                printf("| %8d   %8d   |\n", j + 1, fileit->second.tab[j]);
            printf("|-----------------------|\n");
        }
    }
}
//输出文件目录和 fat
void info()
{
    printf("|-------------------------------|\n");
    printf("|-----------文件目录------------|\n");
    printf("|-------------------------------|\n");
    printf("|  文件名   起始位置  逻辑长度  |\n");
    for (int i = 1; i <= fd.filenum; i++)
        printf("|  %6s  %8d  %9d  |\n", fd.name[i].c_str(), fd.start[i], fd.filelength[i]);
    printf("|-------------------------------|\n");
    printf("\n|--------------------|\n");
    printf("|---文件定位表(fat)--|\n");
    printf("|--------------------|\n");
    printf("|    索引    内容    |\n");
    printf("|      0      FDF    |\n");
    printf("|      1      FFF    |\n");
    for (int i = 2; i < 32; i++)
        printf("|   %4d    %4d     |\n", i, fat[i]);
    printf("|--------------------|\n\n");
}

//功能选择清单
void choicelist()
{
    cout << "|====================================================================|" << endl;
    cout << "|---------------MS-DOS磁盘文件存储管理菜单和索引文件结构-------------|" << endl;
    cout << "|                      1.向fat中存储一个文件:                        |" << endl;
    cout << "|                      2.向fat中的文件插入数据:                      |" << endl;
    cout << "|                      3.输出当前文件目录以及fat信息:                |" << endl;
    cout << "|                      4.转换成索引表:                               |" << endl;
    cout << "|                      5.输出转换后的索引表:                         |" << endl;
    cout << "|                      6.结束操作,退出系统:                         |" << endl;
    cout << "|====================================================================|" << endl;
}

int main()
{

    char name[10];
    init();
    int order;
    while (1)
    {
        //通过字符串输入来选择想要测试的功能
        choicelist();
        cout << "请输入你要执行的操作的编号: ";
        cin >> order;
        switch (order)
        {
        //存 一个文件
        case 1:
            save();
            break;
        //在指定的文件中的特定位置插入一个块
        case 2:
            insert();
            break;
        //显示当前的系统信息
        case 3:
            info();
            break;
        //测试结束退出系统3
        case 4:
            change_to_index();
            break;
        case 5:
            info_change_after();
            break;
        case 6:
            cout << "系统结束" << endl;
            exit(0);
            break;
        //输入指令不合法
        default:
            cout << "指令输入错误" << endl;
        }
    }
    return 0;
}
程序初值和运行结果

转化成索引表:

image-20211219194600309

打印当前文件索引表:

image-20211219194647820

插入文件后输出文件fat表

image-20211219194915960

将新插入的文件加入索引结构中:

image-20211219194954473

image-20211219195026995

思考题:

1. 链表文件结构和索引文件结构各自的优缺点是什么?

  • 链式结构

    优点:

    1. 动态数据结构:链表是一种动态数据结构,因此它可以在运行时通过分配和取消分配内存来增长和缩小。所以没有必要给出链表的初始大小。
    2. 易于插入和删除:在链表中进行插入和删除节点真的很容易。在链表中,我们只需要更新节点下一个指针中的地址。
    3. 磁盘空间利用率、内存利用率高:由于链表的大小可以在运行时增加或减少,因此没有内存浪费。

    缺点:

    1. 存取速度慢,不适于随机存取;
    2. 当物理块间的连接指针出错时,数据丢失;
    3. 更多的寻道次数和寻道时间;链接指针占用一定的空间,降低了空间利用率。
  • 索引结构
    优点:

    1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性;
    2. 可以大大加快数据的检索速度,这也是创建索引的最主要的原因;可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义;
    3. 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间;
    4. 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

    缺点:

    1. 创建索引和维护索引要耗费时间,因为这导致了较多的寻道次数和寻道时间,这种时间随着数据量的增加而增加;
    2. 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大;
    3. 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

2.当文件较大时,使得索引表也较大,如果索引表的大小超过了一个物理块,如何进行索引表的存取?

如果索引表的大小超过了一个物理块,可以采用间接索引(多重索引)的方式来解决,也就是在索引表所指的物理块中存放的不是文件信息,而是装有这些信息的物理块地址,这样,如果一个物理块可装下n个物理块地址,则经过一级间接索引,可寻址的文件长度将变为n×n块。如果文件长度还大于n×n块,还可以进行类似的扩充,即二级间接索引。

这样就对索引表的长度没有限制了,但是同时也会增加很多空间上的开销。如果是使用分页式管理位示图算法,文件存储的时候是按照块来分割的,内存的空间也是按照块来分割的,所以就一定是能够充分利用内存空间的,不会造成浪费。但是同时,这种算法实现起来复杂度较高,虽然寻找空闲块比较简单,但是文件的读取和存储都是分块进行的,而且位置之间没有顺序性,所以读取和存储的寻址和处理的时间代价很大,算法复杂度较高。另外,这种算法是需要页表来进行维系的,页表也需要存储,会造成空间的浪费,如果内存分块块比较小,数量很多,会导致页表非常大,极限情况下,内存会被页表完全占领,造成极大的浪费,效率受到影响。

五、实验总结

本次实验第一题相对比较容易,通过用数组来模拟链表结构可以成功实现,第二题的难点在于三级索引结构的设计,如果都使用结构体使得代码较为复杂冗长,所以经过思考后,我采用了stl中的map来作为用户名和文件表的映射以及文件名和索引表的映射,这使得代码量大大减小,成功实现该功能。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值