文件系统(操作系统实验)

实验内容

(1)在内存中开辟一个虚拟磁盘空间作为文件存储器, 在其上实现一个简单单用户文件系统。 在退出这个文件系统时,应将改虚拟文件系统保存到磁盘上, 以便下次可以将其恢复到内存的虚拟空间中。

(2)要求提供有关操作:format, create, rm, mkdir, rmdir, ls…

format:对文件存储器进行格式化,即按照文件系统对结构对虚拟磁盘空间进行布局,并在其上创建根目录以及用于管理文件存储空间等的数据结构。

mkdir:用于创建子目录;

rmdir:用于删除目录;

ls:用于显示目录;

cd:用于更改当前目录;

create:用于创建文件;

open:用于打开文件;

close:用于关闭文件;

write:用于写文件;

read:用于读文件

rm:用于删除文件

实验原理:

磁盘分区方式:

superblock super; // 超级块

FAT fat;           // FAT 表

bitmap bm;         // 磁盘块的位识图

inodemap im;       // 索引节点的位示图

inode inodes[INODE_SUM]; // 索引节点

inode root;               // 根目录的索引节点

block blocks[BLOCK_SUM]; // 其他索引节点

文件管理系统数据成员:

disk *diskptr;                          // 管理的虚拟磁盘

char *filepath;                         // 虚拟磁盘保存的位置

Buf wdir;                               // 工作目录

Buf wfile;                              // 文件操作缓冲区

Filebuf wprt[10];                       // 读写指针

int cur_blockid = 0;                    // 当前工作目录下的第一个盘块

int cur_inode = -1;                     // 当前工作目录下的索引节点

string workpath;

算法思路:

用FAT表对磁盘块进行链接存储,索引节点和磁盘块均采用位示图的方式进行管理和分配根节点的索引节点号为 -1。

对文件或者目录进行修改删除时,均先切换到对应得目录下再进行操作,执行完毕后再返回原来得工作目录。

程序退出时先将虚拟磁盘写回到目录再退出。

编译执行命令: g++ -o main *.cpp && ./main

效果展示

列出当前目录项得文件和文件夹

查看文件内容

创建文件夹

删除文件夹

创建文件,并读写文件

程序退出时保存原来得磁盘情况

保存的磁盘文件 16进制展示

超级块和部分FAT表

部分根目录:

保存的部分文件内容

保存的磁盘文件大小:

部分源码

data.hpp

#pragma once
#define BLOCK_SIZE 512      // 磁盘块大小 512 B
#define ENTRIES_PER_BLOCK 4 // 每个磁盘块最多 4 个目录项
#define BLOCK_SUM 2048      // 磁盘块数
#define INODE_SUM 2048      // 索引节点数
#define DIRSTY 0            // 目录
#define FILESTY 1           // 普通文件
#define READ 1              // 读权限
#define WRITE 2             // 写权限

disk.hpp

#pragma once
#include "data.hpp"

class superblock
{
public:
    int block_sum; // 盘块的数量
    int inode_sum; // 索引节点的数量
    superblock();
};

class FAT
{
public:
    int next[BLOCK_SUM]; // 链表法
    FAT();
};

class bitmap
{
public:
    char map[BLOCK_SUM / 8]; // 位示图
    bool empty(int no);      // 判断磁盘块是否分配
    void set(int);           // 将磁盘块置为已分配
    void free(int);          // 回收磁盘块
    bitmap();                // 初始化,全部为未分配
    int get();               // 申请一个磁盘块,成功则返回磁盘块号,否则返回 -1
};

class inodemap
{
public:
    char map[INODE_SUM / 8];
    bool empty(int no); // 返回当前节点是否为空
    void set(int);
    void free(int);
    inodemap(); // 初始化位示图
    int get();
};

class inode
{
public:
    int firstblock; // 第一个盘块号
    int type;       // 文件类型
};

class entry
{
public:
    bool flag;      // 目录项是否有效
    char name[123]; // 文件名
    int node;       // 索引节点号
    entry();
};

union block // 磁盘块,有两种组织形式,普通文件目录的形式
{
public:
    char data[BLOCK_SIZE];
    entry entries[ENTRIES_PER_BLOCK];
    block();
};

class disk
{
public:
    superblock super;
    FAT fat;
    bitmap bm;
    inodemap im;
    inode inodes[INODE_SUM];
    inode root;
    block blocks[BLOCK_SUM];
    disk();
};

FS.hpp

#pragma once
#include <string>
#include "disk.hpp"
using std::string;

union Buf // 缓存区,主要用于将目录、文件放到缓冲区处理
{
    entry entries[4096];
    char data[524288];
    block blocks[512];
    Buf();
};

class Filebuf // 读文件工作区,保存已经打开的文件及权限
{
public:
    bool flag = false;
    inode fnode;
    char mod = 0;
    char name[123];
    int fafblock; // 父目录的第一个盘块
};

class FS
{
    disk *diskptr;                          // 管理的虚拟磁盘
    char *filepath;                         // 虚拟磁盘保存的位置
    Buf wdir;                               // 工作目录
    Buf wfile;                              // 文件操作缓冲区
    Filebuf wprt[10];                       // 读写指针
    int cur_blockid = 0;                    // 当前工作目录下的第一个盘块
    int cur_inode = -1;                     // 当前工作目录下的索引节点
    void loadbuf(int firstblock, Buf &buf); // 载入缓冲区,可以执行工作目录和文件操作缓冲区的加载
    void writebackdir(int firstblock);      // 写回目录,常常在切换工作目录时写回
    void writebackfile(int firstblock);     // 写回文件,完成写文件后写回
    void delfile(int firstblock);           // 删除文件,包括目录和普通文件

    /*------------------ 原子操作(只允许在当前目录下操作) --------------------------------------*/
    int cd(const char *);      // 切换目录,原子操作,返回 1 表示没有该目录
    void create(const char *); // 创建文件
    void rmdir(const char *);  // 删除文件
    void mkdir(const char *);  // 创建目录
    void ls();                 // 列出当前目录下的文件和文件夹

    string getfolerpath(string);
    string getfilename(string);

public:
    string workpath;
    FS(char *file); // 对磁盘格式化,或导入已有的磁盘文件
    ~FS();          // 写回磁盘并保存

    /*------------------ 原子操作(只允许在当前目录下操作) --------------------------------------*/
    int open(const char *, char mod); // 返回一个 wptr,只能打开当前目录的文件
    void write(int, const char *);    // 写文件,第一个参数为写指针,第二个参数为写的内容
    void close(int);                  // 关闭文件
    void read(int);                   // 读文件,参数为读指针
    void rm(int);                     // 删除文件,需要先打开文件才能删除

    /*--------------------- 允许任何在路径下操作(只有changedir 会改变工作路径)------------------------------*/
    int changedir(const char *);                // 切换工作目录
    void createfile(const char *);              // 创建文件,参数为文件路径
    void removedir(const char *);               // 删除文件夹,参数为文件夹路径
    void list(const char *);                    // 列出指定目录下的文件和文件夹
    void makedir(const char *);                 // 创建文件夹,参数为文件夹路径
    int openfile(const char *, char);           // 打开指定文件,第二个参数为读写权限,返回读写指针
    void writefile(const char *, const char *); // 写文件,第一个参数为文件路径,第二个为写入内容
    void readfile(const char *);                // 读文件
    void removefile(const char *);              // 删除文件
};

main.cpp

#include <iostream>
#include <string>
#include "FS.hpp"
using namespace std;

char file[] = "./FileSys";
FS fs(file);

int main()
{
    cout << "/>";
    string op;
    string contxt;
    string par;
    int wptr;
    while (cin >> op)
    {
        if (op == "ls")
        {
            char a = getchar();
            if (a == '\n')
            {
                char path[] = ".";
                fs.list(path);
            }
            else
            {
                cin >> par;
                fs.list(par.c_str());
            }
        }
        if (op == "cd")
        {
            cin >> par;
            fs.changedir(par.c_str());
        }
        if (op == "touch")
        {
            cin >> par;
            fs.createfile(par.c_str());
        }
        if (op == "mkdir")
        {
            cin >> par;
            fs.makedir(par.c_str());
        }
        if (op == "rmdir")
        {
            cin >> par;
            fs.removedir(par.c_str());
        }
        if (op == "open")
        {
            cin >> par;
            wptr = fs.openfile(par.c_str(), READ | WRITE);
        }
        if (op == "write")
        {
            cin >> par;
            char line[524288];
            contxt = "";
            cin.get();
            cin.getline(line, 524288, '\n');
            cin.clear();
            while (string(line) != "EOF")
            {
                contxt += string(line) + '\n';
                cin.getline(line, 1024, '\n');
                cin.clear();
            }
            fs.writefile(par.c_str(), contxt.c_str());
        }
        if (op == "cat")
        {
            cin >> par;
            fs.readfile(par.c_str());
        }
        if (op == "rm")
        {
            cin >> par;
            fs.removefile(par.c_str());
        }
        if (op == "quit")
            break;
        if (op == "close")
        {
            fs.close(wptr);
        }
        cout << fs.workpath << ">";
    }
}

doc.txt(转载自China Daily)

Precipitation on Tibetan Plateau underestimated
By YAN DONGJIE | China Daily | Updated: 2024-06-07 09:17
Precipitation across the Tibetan Plateau, which is known as Asia's water tower, has been significantly underestimated, Chinese researchers said in a paper published in the Proceedings of the National Academy of Sciences late last month.
The researchers, from the Chinese Academy of Sciences' Institute of Tibetan Plateau Research, said the underestimation is caused by the measuring instruments used and the method of calculation, and called for a "redesigned precipitation observation strategy" to remedy it.
A substantial proportion of precipitation over the plateau falls as snow, often accompanied by strong winds.
The researchers said ground-based instrument monitoring is widely regarded as the primary and most reliable technique for acquiring precipitation data, but traditional ground-level precipitation gauges have a limited cross-section in the collection cylinder and a sealed bottom.
"This design results in the formation of upward supporting airflow under windy conditions, which in turn prevents raindrops or snowflakes from entering the gauge cylinder. Consequently, this leads to an underestimation of precipitation in this region," said Miao Chiyuan from Beijing Normal University, the first author of the study.
Miao said the instrument measurement error caused by strong winds is the primary factor affecting the accuracy of precipitation measurements in high-altitude regions, with errors under extreme weather conditions potentially exceeding 100 percent.
Apart from the equipment, variations in altitude can cause mistakes in the data collected. Weather stations in the region are often placed in valleys or lower areas for convenience, which means they miss out on precipitation that occurs at higher elevations. Additionally, the limited number of stations and their uneven distribution can make the data even less accurate, according to the study.
The Tibetan Plateau, home to more than 100,000 square kilometers of glaciers and 1 million sq km of frozen soil, serves as the source of 10 major Asian river systems flowing into 10 countries, and supports the lives of about 2 billion people.
"In the context of accelerated warming, precipitation across the Tibetan Plateau plays a critical role in water cycles. Accordingly, obtaining reliable precipitation information is a prerequisite for water cycle analysis, future climate projections, and water-related disaster risk assessments," said the institute's Li Xin, the corresponding author of the research.
EOF

file.txt

Desktop
Documents
Downloads
Music
Pictures
Public
Templates
Videos
snap
Desktop/lab1
Desktop/lab2
Desktop/lab3
Desktop/lab4
Desktop/lab5
snap/firefox
snap/firefox/3836
snap/firefox/4336
snap/firefox/common
snap/snapd-desktop-integration
snap/snapd-desktop-integration/83
snap/snapd-desktop-integration/common

存储大文件存在一点问题,自行修改

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

llama.cpp

https://github.com/echonoshy/cgft-llm 【大模型量化】- Llama.cpp轻量化模型部署及量化_哔哩哔哩_bilibili github.com/ggerganov/llama.cpp cd ~/code/llama.cpp/build_cuda/bin ./quantize --allow-requantize /root/autodl-tmp/models/Llama3-8B-Chinese-Chat-GGUF/Llama…

项目训练营第六天

项目训练营第六天 前端注册界面开发 1、基本布局 将登录界面文件夹复制一份&#xff0c;粘贴到上一层目录User目录下&#xff0c;改名为Register 在typings.d.ts文件中添加如下的登录前端接口函数标准参数 以及返回值类型 2、接口开发 在api.ts中修改原先接口如下&…

3.SQL注入-搜索型

SQL注入-搜索型 输入k字段进行搜索发现出用户信息 通过上图搜索可以猜测的sql语句为 select 字段1,字段2 from 表名 where username like %k%;在后台查询结果 select id,email from member where username like %k%;通过以上猜测进行构造payload语句 like %k% or 11 #%; …

mysql_config 命令, 可以查看mysqlclient库的位置在/usr/lib64/mysql下

好吧&#xff0c;其实我是从这里知道了 -l 后面加的库名和so文件这种名不一样&#xff0c;因为库文件实际叫下面这个名&#xff08;前面有lib)。

零基础开始学习鸿蒙开发-页面导航栏布局设计

1.设定初始页(Idex.ets) import {find} from ../pages/find import {home} from ../pages/home import {setting} from ../pages/setting Entry Component struct Index {private controller: TabsController new TabsController()State gridMargin: number 10State gridGut…

【漏洞复现】致远互联FE协作办公平台——SQL注入

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 致远互联FE协作办公平台是一个专注于协同管理软件领域的数智化运…

论文学习——一种自适应提升的动态多目标优化进化算法

论文题目&#xff1a;A dynamic multi-objective optimization evolutionary algorithm with adaptive boosting 一种自适应提升的动态多目标优化进化算法&#xff08;Hu Peng a,b,∗, Jianpeng Xiong a, Chen Pi a, Xinyu Zhou c, Zhijian Wu d&#xff09;IEEE Swarm and Ev…

【Python游戏】猫和老鼠

本文收录于 《一起学Python趣味编程》专栏,从零基础开始,分享一些Python编程知识,欢迎关注,谢谢! 文章目录 一、前言二、代码示例三、知识点梳理四、总结一、前言 本文介绍如何使用Python的海龟画图工具turtle,开发猫和老鼠游戏。 什么是Python? Python是由荷兰人吉多范…

LeetCode热题100刷题2:283. 移动零、11. 盛最多水的容器、15. 三数之和、42. 接雨水

283. 移动零 挺简单的没啥说的 class Solution { public:void moveZeroes(vector<int>& nums) {//快慢指针 // 快指针负责往前遍历&#xff0c;慢指针记录快指针遍历过的把0撵走的最后一个元素的位置// 然后快指针遍历完之后&#xff0c;慢指针到结尾直接赋0就行in…

2-20 基于matlab的利用准二维发散喷嘴的特性法给出理想喷嘴的几何形状

基于matlab的利用准二维发散喷嘴的特性法给出理想喷嘴的几何形状。 假设气体从燃烧室排出&#xff0c;燃烧室内没有质量流量。 利用二维喷嘴流动关系&#xff0c;找到一个最佳喉管区域&#xff0c;该区域将在给定环境压力和燃烧室参数下产生最大推力。 该区域将自动设置并输入代…

Webpack: 7 款常用的性能分析工具

概述 Webpack 最大的优势在于它的功能非常强大、全面&#xff0c;加之繁荣活跃的组件生态&#xff0c;已经足够应对几乎所有 Web 构建需求&#xff0c;包括&#xff1a;SPA、MPA、SSR、桌面应用、Node 程序、WebAssemsbly、PWA、微前端等等&#xff0c;所以即使在近几年工程化…

网络io与select,poll,epoll

前言 网络 IO&#xff0c;会涉及到两个系统对象&#xff0c;一个是用户空间调用 IO 的进程或者线程&#xff0c;另一个是内核空间的内核系统&#xff0c;比如发生 IO 操作 read 时&#xff0c;它会经历两个阶段&#xff1a; 1. 等待数据准备就绪 2. 将数据从内核拷贝到进程或…

产品经理-对产品经理的认识(1)

今天跟大家聊一下产品经理这个岗位的,产品经理是互联网岗位当中比较火的一个岗位,也是最接近CEO的岗位 产品经理岗位&#xff0c;技术门槛低&#xff0c;薪水和前景都很不错&#xff0c;又处于团队的核心位置 产品经理岗位没有完全相关的专业设置和清晰的学习路径&#xff0c;绝…

HarmonyOS Next开发学习手册——选项卡 (Tabs)

当页面信息较多时&#xff0c;为了让用户能够聚焦于当前显示的内容&#xff0c;需要对页面内容进行分类&#xff0c;提高页面空间利用率。 Tabs 组件可以在一个页面内快速实现视图内容的切换&#xff0c;一方面提升查找信息的效率&#xff0c;另一方面精简用户单次获取到的信息…

第11章 规划过程组(11.5创建WBS)

第11章 规划过程组&#xff08;一&#xff09;11.5创建WBS&#xff0c;在第三版教材第380~383页&#xff1b; 文字图片音频方式 视频22 第一个知识点&#xff1a;主要输入 1、项目管理计划 范围管理计划 定义了如何根据项目范围说明书创建WBS2、项目文件 项目范围说明…

实验三 时序逻辑电路实验

仿真 链接&#xff1a;https://pan.baidu.com/s/1z9KFQANyNF5PvUPPYFQ9Ow 提取码&#xff1a;e3md 一、实验目的 1、通过实验&#xff0c;理解触发的概念&#xff0c;理解JK、D等常见触发器的功能&#xff1b; 2、通过实验&#xff0c;加深集成计数器功能的理解&#xff0c;掌…

Docker部署Dillinger个人文本编辑器

Docker部署Dillinger个人文本编辑器 一、Dillinger介绍1.1 Dillinger简介1.2 Dillinger使用场景 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、拉取Dillinger镜像五、部署Dill…

创建一个vue3+vite+ts项目

目录 创建项目 ​编辑 下载jsx 插件 在根目录在新建.env vue.config.js tsconfig.json tsconfig.node.json 下载ui组件库和路由&#xff08;组件库根据自己的项目需要选择&#xff09; 在根目录下新建views/index.tsx 在根目录下新建router/index.ts 修改App.vue 创建…

机器学习笔记 人脸识别技术全面回顾和小结(2)

一、现实条件 随着人脸识别研究的深入&#xff0c;研究者开始关注现实条件下的人脸识别问题&#xff0c;主要包括以下几个方面的研究。首先&#xff0c;我们分析和研究了影响人脸识别的因素。第二&#xff0c;新特征表示的使用研究。第三&#xff0c;使用新数据源的研究。如表1…

TDD测试驱动开发

为什么需要TDD&#xff1f; 传统开发方式&#xff0c;带来大量的低质量代码&#xff0c;而代码质量带来的问题&#xff1a; 1.在缺陷的泥潭中挣扎 开发长时间投入在缺陷的修复中&#xff0c;修复完依赖测试做长时间的回归测试 2.维护困难&#xff0c;开发缓慢 比如重复代码&am…