【操作系统】磁盘存储空间的管理

实验5 磁盘存储空间的管理

一、实验目的

    磁盘是用户存放程序和数据的存储设备,磁盘管理的主要目的是充分有效地利用磁盘空间。本实验模拟实现磁盘空间的分配与回收,使学生对磁盘空间的管理有一个较深入的理解。

二、实验内容

实验任务:用位示图管理磁盘空间实现磁盘块的分配与回收

(1)假定现有一个磁盘组,共有8个柱面。每个柱面有4个磁道,每个磁道又划分成4个物理盘块。磁盘的空间使用情况用位示图表示。位示图用若干个字构成,每一位对应一个磁盘块。“1”表示占用,“0”表示空闲。假定字长为16位,一个字可用来模拟磁盘的一个柱面,其位示图如下图所示。位示图的初始状态为第1个字为“1”,其他全部空闲。

字/位

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

2

…..

7

(2)为文件分配磁盘空间。首先输入文件信息,主要包括文件名、文件大小等信息;然后根据位示图为文件分配磁盘块,磁盘块可以不连续分配。要求输出分配的磁盘块的相对块号和其绝对地址CHS(柱面号、磁头号、扇区号),输出位示图。

(3)释放文件所占的磁盘空间。输入文件名,释放其所占的磁盘空间。要求输出该文件所分配的磁盘块的相对块号和其绝对地址CHS,输出位示图。

(4)根据用户选择输出磁盘位示图和磁盘中的所有文件信息。

三、测试用例

(0)初始磁盘位示图和文件列表

(1)首先为3个以上的文件分配磁盘空间

设置f1、f2、f3三个文件,文件申请的磁盘空间大小分别为5KB、10KB、20KB。

【1】创建f1文件,文件大小为5KB。

【2】创建f2文件,文件大小为10KB。

【3】创建f3文件,大小为20KB。

(2)删除先创建的一个文件

删除f1文件。可以看到扇区16~扇区20已经被设置为0,表示未分配(空闲)扇区。

(3)为新的文件分配磁盘空间,容量大于刚刚删除掉的那个文件

重新申请f1文件,文件大小为30KB。

(4)随机删除各个文件,看看磁盘空间的变化情况

【1】删除f2文件

【2】删除f3文件

【3】删除f1文件

(5)所有的文件都删除掉时,磁盘恢复为初始化状态

如第(4)步中【3】删除f1文件所示。

程序使用完毕后,退出系统。

四、实验分析与总结

1)数据结构说明

【1】FCB的数据结构

    FCB的代码实现如下图所示。

在本实验中,利用struct构造FileInfo结构体,实现对文件基本信息的记录,即文件控制块。

该数据结构的基本变量包括:文件名字的字符串file_name、文件大小的整型单变量file_size、文件分配扇区的一维数组allocated_sectors。

【2】磁盘空间的数据结构

磁盘空间的代码实现如下图所示。

在本实验中,利用struct构造StorageManager结构体,实现磁盘空间的初始化和管理。

该数据结构的基本变量包括:可用扇区总数的整型单变量available_sectors、磁盘位示图的二维数组bitmap、文件映射的哈希表files。

该数据结构的功能包括:构造磁盘空间函数createFile、创建文件(给文件分配磁盘空间)函数createFile、显示磁盘存储状态函数displayStatus、显示磁盘中的文件序列函数fileDetails、删除文件(回收给文件分配的磁盘空间)函数deleteFile。

2)程序流程图

【1】主函数的程序流程图

主要代码段:

对应流程图:

【2】构造磁盘空间函数的程序流程图

【3】创建文件(给文件分配磁盘空间)函数的程序流程图

【4】显示磁盘存储状态函数的程序流程图

【5】显示磁盘中的文件序列函数的程序流程图

【6】删除文件(回收给文件分配的磁盘空间)函数的程序流程图

【7】菜单函数的程序流程图

3)程序运行结果,打印程序运行时的初值和运行结果

如【三、测试用例】中所示。测试的流程图如下图所示。

4)实验知识点总结和实验收获与体会

1:加深了对磁盘存储空间管理的理解,将抽象的概念应用到实际情况中。位示图演示了如何有效地管理资源,特别是在多个文件竞争相同磁盘块的情况下。实际磁盘操作的各步骤内容如下所示。

步骤

具体内容

步骤1:初始化位示图

初始化一个位示图来表示磁盘空间的占用情况。

使用16位字来表示一个柱面的状态,初始状态为第一个字为"1",其余全部为"0",表示柱面1被占用,其余柱面为空闲。

步骤2:文件分配磁盘空间

用户输入文件信息,包括文件名和文件大小。

根据位示图为文件分配磁盘块,可以不连续分配。这意味着文件的数据块可以分散在磁盘上。

输出分配的磁盘块的相对块号和其绝对地址CHS(柱面号、磁头号、扇区号)。

更新位示图以反映已分配的磁盘块状态。

步骤3:释放文件所占的磁盘空间

用户输入要释放的文件名。

根据文件名查找该文件所占用的磁盘块。

输出被释放的磁盘块的相对块号和其绝对地址CHS。

更新位示图以反映已释放的磁盘块状态。

步骤4:输出磁盘位示图和文件信息

用户可以选择输出磁盘位示图,以查看磁盘空间的占用情况。

用户还可以选择输出磁盘中的所有文件信息,包括文件名、大小和存储位置等信息。

2:位示图法是磁盘空间管理方法的其中一个,用于盘块的分配、回收,并且涉及绝对地址与逻辑盘块之间的转换。磁盘上的所有盘块都有一个bit与之对应,由所有盘块所对应的位构成一个集合,称为位示图。位示图主要是由二维数组表示的,其中行号称为字号,列号称为位号。位示图的示例图如下所示。

3:磁盘块是存储介质上连续扇区所组成的一个区域,也被称作物理块、簇。磁盘块的重要性如下:①读取方便:由于扇区的存储数量比较小,所以OS将相邻的扇区组合在一起,形成一

个块,再对块进行整体的操作。②分离对底层的依赖:OS忽略对底层物理存储结构的设计。通过虚拟出来磁盘块的概念,在系统中认为块是最小的单位。

4:块是主存和辅助进行信息交换的最小单位,每次总是交换一块或整数块信息。

5:磁盘的物理地址CHS由柱面(Cylinder)、磁头(Head)、扇区(Sector)构成。磁盘的物理结构如下图所示。

6:在逻辑盘块地址LBA与物理地址CHS的转换中,假设磁头数是n,每个磁道的扇区数是m,则柱面号、磁头号、扇区号的计算公式如下所示。

目标计算量

计算公式

柱面号C

C = LBA / (n * m)

磁头号H

H = (LBA / m) % n

扇区号S

S = (LBA % m)

7:磁盘管理的其他方法包括:空闲表法(主要用于交换区管理,可采用的分配算法有首次适应算法和最佳适应算法)、空闲链法(FAT系统采用,包括空闲盘块链和空闲盘区链)、成组链接法(Linux系统采用,采用了空闲表和链表进行结合)。

6)实验源代码

#include <iostream>

#include <vector>

#include <unordered_map>

using namespace std;

// 文件信息结构体(FCB,file control block)

struct FileInfo {  

    string file_name;               // 文件名字

    int file_size;                  // 文件大小

    vector<int> allocated_sectors;  // 文件分配的扇区

};

// 存储管理器结构体(磁盘管理)

struct StorageManager {                    

    int available_sectors;                  // 可用扇区总数

    vector<vector<int>> bitmap;             // 磁盘位图

    unordered_map<string, FileInfo> files;  // 文件映射

    StorageManager();                       // 构造函数

    bool createFile(const string&, int);    // 创建文件

    void displayStatus();                   // 显示存储状态

    void fileDetails(const FileInfo&);      // 显示文件详情

    bool deleteFile(const string&);         // 删除文件

};

// 构造函数

// 假定现有一个磁盘组,共有8个柱面。每个柱面有4个磁道,每个磁道又划分成4个物理盘块。

StorageManager::StorageManager() : available_sectors(128) {

    bitmap.resize(8, vector<int>(16, 0));   // 构造8*16个空盘块

    for (int j = 0; j < 16; ++j) {

        bitmap[0][j] = 1;  // 预留第一行作为系统文件,该柱面不可用

        // 位示图的初始状态为第1个字为“1”,其他全部空闲。

    }

}

// 创建文件函数

bool StorageManager::createFile(const string& name, int size) {

    if (files.find(name) != files.end()) {  // 如果文件名字不在末尾,则冲突

        cout << "错误: 文件已存在。"<< endl;

        return false;

    }  

    if (size > available_sectors) {     // 如果文件大小大于空闲扇区大小

        cout << "错误: 空间不足。"<< endl;

        return false;

    }

   

    // 创建新文件的FCB

    FileInfo newFile{ name, size, {} };

   

    // 更新位示图中信息

    for (int i = 0; i < bitmap.size() && size > 0; ++i) {

        for (int j = 0; j < bitmap[i].size() && size > 0; ++j) {

            if (bitmap[i][j] == 0) {    // 如果这个盘块为空

                bitmap[i][j] = 1;   // 设置为已经分配

                newFile.allocated_sectors.push_back(i * 16 + j);    // 分配区增加这个盘块

                --size;     // 空闲区大小-=1

                --available_sectors;    // 同上

            }

        }

    }

    files[name] = newFile;  // hash表设置

    fileDetails(newFile);   // 显示新建文件详情

    return true;

}

// 显示磁盘分配情况函数

void StorageManager::displayStatus() {

    cout << "磁盘位图:" << endl;

    for (int i = 0; i < bitmap.size(); ++i) {

        for (int j = 0; j < bitmap[i].size(); ++j) {

            cout << bitmap[i][j] << ' ';

        }

        cout << endl;   // 换行显示

    }

   

    cout << endl << "文件列表:" << endl;

    for (const auto& pair : files) {

        cout << pair.first << "\t大小: " << pair.second.file_size << endl;

    }

    cout << endl;

}

// 显示文件内存详情函数

void StorageManager::fileDetails(const FileInfo& file) {

    cout << "文件 '" << file.file_name << "' 的详细信息:"<< endl;

    for (int sector : file.allocated_sectors) {

        cout << "扇区: " << sector << ";";    //遍历扇区

    }

    cout << endl;

}

// 删除文件函数

bool StorageManager::deleteFile(const string& name) {

    auto it = files.find(name);

    if (it == files.end()) {

        cout << "错误: 文件不存在。"<< endl;

        return false;

    }

    for (int sector : it->second.allocated_sectors) {

        int i = sector / 16;

        int j = sector % 16;

        bitmap[i][j] = 0;

        ++available_sectors;

    }

    files.erase(it);

    cout << "文件 '" << name << "' 已删除。"<< endl;

    return true;

}

// 菜单函数

void menu(StorageManager manager){

    manager.displayStatus();

    cout << "根据数字提示选择操作: ";

    cout << endl << "1:创建文件, 2:删除文件, 3:退出系统"<< endl;

}

// 主函数

int main() {

    StorageManager manager;

    int action;

    string filename;

    int filesize;

    while (true) {

        cout << endl;

        menu(manager);

        cin >> action;

        switch (action) {

            case 1:

                cout << "输入文件名: ";

                cin >> filename;

                cout << "输入文件大小: ";

                cin >> filesize;

                if (manager.createFile(filename, filesize)) {

                    cout << "文件创建成功。\n";

                }

                break;

            case 2:

                cout << "输入要删除的文件名: ";

                cin >> filename;

                if (manager.deleteFile(filename)) {

                    cout << "文件删除成功。\n";

                }

                break;

            case 3:

                cout << "程序退出。\n";

                return 0;

            default:

                cout << "无效的操作。\n";

        }

    }

    return 0;

}

/*

测试用例:

【创建文件】

1

f1

5

 

1

f2

10

1

f3

20

【删除f1】

2

f1

【重新创建更大的f1】

1

f1

10

【随机删除】

2

f2

2

f3

2

f1

【结束】

*/

五、实验指导

(1)程序主框架和数据结构

程序主框架可参考内存管理实验,功能主要包括:分配空间、回收空间、打印位示图、打印文件信息等。

数据结构主要包括:

位示图:保存磁盘分配情况;

文件基本信息表:包括文件名、文件长度、创建时间、文件分配的相对磁盘号等。

2)申请和释放磁盘块操作

申请一个磁盘块时,由磁盘管理程序检查位示图,找出一个为0的位,计算磁盘的物理地址,即求出它的柱面号、磁道号和扇区号。

释放一个相对物理块时,磁盘管理程序计算该块在位示图中的位置,再把相应由“1”改为“0”。由相对块号计算字号和位号。

3)磁盘空间分配和回收流程图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/485143.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业计算机服务器中了crypt勒索病毒怎么办,crypt勒索病毒解密数据恢复

计算机服务器设备为企业的生产运营提供了极大便利&#xff0c;企业的重要核心数据大多都存储在计算机服务器中&#xff0c;保护企业计算机服务器免遭勒索病毒攻击&#xff0c;是一项艰巨的工作任务。但即便很多企业都做好的了安全运维工作&#xff0c;依旧免不了被勒索病毒攻击…

方法:Linux/Windows进程和端口如何相互求证

1. 问题描述 开发过程中&#xff0c;我们经常会遇到这样的情况&#xff1a; 服务A启动&#xff0c;提示端口被占用&#xff0c;导致服务无法正常工作&#xff0c;需要查看端口被哪个进程占用了。服务A启动&#xff0c;正常监听&#xff0c;等待连接、请求&#xff0c;但是第三…

Flutter NestedScrollView 内嵌视图滚动行为一致

Flutter NestedScrollView 内嵌视图滚动行为一致 视频 https://youtu.be/_h7CkzXY3aM https://www.bilibili.com/video/BV1Gh4y1571p/ 前言 上一节讲了 CustomScrollView &#xff0c;可以发现有的地方滚动并不是很连贯。 这时候就需要 NestedScrollView 来处理了。 今天会写…

更高效的构建工具-vite

更高效的构建工具-vite 前言Vite是什么Vite和webpack的比较1. 运行原理2. 使用成本 Vite的初体验 前言 首先我们要认识什么时构建工具&#xff1f; 企业级项目都具备什么功能呢&#xff1f; Typescript&#xff1a;如果遇到ts文件&#xff0c;我们需要使用tsc将typescript代码…

Mac Jmeter下载安装启动(1)

目录 Jmeter下载安装启动下载启动 Jmeter下载安装启动 注意⚠️&#xff1a;使用jmeter需要有java环境 下载 官网下载地址&#xff1a;https://jmeter.apache.org/ 会看到这里有两个版本&#xff0c;那么有什么区别么&#xff1f; Binaries是可执行版&#xff0c;直接下载解…

【开源】SpringBoot框架开发康复中心管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 普通用户模块2.2 护工模块2.3 管理员模块 三、系统展示四、核心代码4.1 查询康复护理4.2 新增康复训练4.3 查询房间4.4 查询来访4.5 新增用药 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的康复中…

新书推荐:《分布式商业生态战略:未来数字商业新逻辑与企业数字化转型新策略》

近两年&#xff0c;商业经济环境的不确定性越来越明显&#xff0c;市场经济受到疫情、技术、政策等多方因素影响越来越难以预测&#xff0c;黑天鹅事件时有发生。在国内外经济方面&#xff0c;国际的地缘政治对商业经济产生着重大的影响&#xff0c;例如供应链中断&#xff0c;…

发布订阅模式:观察者模式的一种变体

发布-订阅模型&#xff08;Publish-Subscribe Model&#xff09;的底层机制通常基于观察者模式。 发布-订阅模型是观察者模式的一种变体。 在观察者模式中&#xff0c;主题&#xff08;或被观察者&#xff09;维护了一组观察者&#xff0c;当主题的状态发生变化时&#xff0c…

【监控】Spring Boot+Prometheus+Grafana实现可视化监控

目录 1.概述 2.spring actuator 3.Prometheus 3.1.介绍 3.2.使用 1.client端的配置 2.server端的配置 4.grafana 5.留个尾巴 1.概述 本文是博主JAVA监控技术系列的第四篇&#xff0c;前面已经聊过了JMX、Spring actuator等技术&#xff0c;本文我们就将依托于Spring …

如何在Mac上启用蓝牙,这里提供几个方法

序言 要将蓝牙配件与Mac配对&#xff0c;首先&#xff0c;你需要在Mac上启用蓝牙。现在有不同的方法可以在Mac上关闭/打开蓝牙&#xff0c;因为苹果macOS集成了Siri。我们将讨论在不使用鼠标的情况下打开蓝牙。为此&#xff0c;激活Siri并要求它打开蓝牙&#xff0c;它将自动启…

PowerDesigner 安装

PowerDesigner 安装汉化破解使用过程 - 沦陷 - 博客园 (cnblogs.com)https://www.cnblogs.com/huangting/p/12654057.html

体验浏览器公司出品的浏览器

朋友&#xff0c;你现在是不是正在使用浏览器看这篇文章&#xff1f; 当然&#xff0c;这篇文章我也是在浏览器中完成的&#xff0c;使用的浏览器就是有叫浏览器公司出品的浏览器。 出品公司&#xff1a;The Browser Company 产品名&#xff1a; Arc Search 下载地址&#xf…