【操作系统】简单FAT文件系统实现

本文介绍了一个简单的FAT文件系统实现,包括初始化、格式化、目录操作、文件读写等功能。在模拟文件系统中,作者遇到并解决了内存对齐等问题。虽然目前不支持多级目录和追加写操作,但提供了对文件系统的详细理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模拟文件系统,在磁盘上创建一个文件,然后在内存中开辟出一段空间出来,然后将内容复制到的内存之中,如果文件不存在,则要先对该区域进行格式话,最后在操作完成之后,将其写会到我们的文件之中。开始和同学一起合作着来写,结果在我不知不自觉中同学写完了,然后出现的问题也挺多的,看起来是非常的费劲,通过这次阅读别人的代码,自己的一个很大的体会就是在逻辑上,还有变量声明上,如果不清晰,让人看起来真的是非常的费劲,自己通了一个宵,总算是理清了思路,然后解决了其中的bug,结果第二天就得了睑门腺炎。但是对于文件的操作,当前还是不支持多级目录的,还有对于文件的写操作,当前只是支持进行覆盖写,还不支持追加写,当然,这个直接借助结构体中声明的一个变量就可以了,实在没有精力写了,由于很久没有碰c这种东西了,现在写起来,感觉真的是怀念java,各种内存读写的问题,也遇到了内存对齐问题。

下面针对代码中的每一个方法,其思路展开一个讲解,最后贴出代码。

startsys()【初始化】

加载本地文件,如果文件不存在,则在内存中开辟出一块空间来,如果存在则将其读到内存中。
获得该内存区域后,对其进行格式化操作,我们得到的空间是原始的,也就是我们常看到的一些存储设备上标记的大小,但是往往我们发现其实际大小是要小的,原因是我们的文件系统在读该块存储区域进行格式化的时候要占据一定的空间。得到这个空间之后,同时为我们的根目录分配了fat块,我们对其将根目录进行设置,添加上两个fcb,对于fcb中的每一项执行相应的初始化操作,同时我们还具有一个表示当前打开层级目录的结构体,openfile,将这个当前目录更新为我们当前的目录。

my_format()【格式化】

  • 引导块

  • Fat1

  • Fat2

fat1和2中存储这相同的东西,每个区域划分两个块的大小,为了提高安全可靠性)
在这里将目录和文件都看做是文件,在每一个目录中要有两个fcb块,分别表示上一级目录和当前目录分别为.和..,通过fcb中的第一块指向信息,来找到我们的fat表,其中包含每一个块的下一块地址,如果一块就结束了,则为其设置上标志位,如果没有存储任何东西,则设置上两一个标志位,然后我们可以通过Fcb中的起始地址,对照fat表进行查表寻找。
格式化后,对fat表中添加fat表项,首先是前5个块被占用了,然后是后面的数据域也就是第六个块,这个目录占有两个块,所以第5个块指向6,第6个块标志为结束,此刻初始化已经完成。

my_mkdir()【创建目录】

  • 获取当前目录的信息,将其读到内存中

  • 判断是否存在该目录

  • 创建一个FCB,判断是否存在一个空的FCB区域,创建一项添加

  • 从Fat表中找到空闲表块

  • 在开辟的新数据区块中创建根目录和当前目录的FCB

do_read()【读入当前目录信息】

  • 接收fat'块和缓存区大小

  • 根据fat块号找到对应根目录位置

  • 读入根目录下的fcb信息,写到缓冲区

do_write()【写文件函数】

  • 根据fat号找到要写回的区域

  • 将之前读入的部分中fcb进行调整,然后写覆盖

my_rmdir()【删除一个目录】

  • 找到当前目录,将其读入到内存中

  • 从其中的fcb进行一个比对,确定是否存在

  • 如果存在根据其first找到对应的fat表,然后判断fat的id找到该内存区域

  • 将fat的id设置为free,fat2的表项也要进行更新。

  • 然后将当前目录中的该fcb项free设置为0

  • 将当前目录的length--;

  • 写回到原来的数据区。

my_ls()【展示当前有哪些目录文件】

  • 得到当前目录执行

  • 根据first指向,然后找到指定的块,根据这个块进行fcb的遍历。

  • 根据其长度进行遍历,同时结合其中的free属性进行检测。

my_create()【创建一个文件】

相比于创建目录,其少了的操作是不需要在其下一块进行一个目录文件的创建

  • 找到当前目录读入内存

  • 对其中的fcb比对,确定是否存在

  • 如果不存在则再去fat表中,添加一项

  • 将fcb块中添加一项,同时将当前的根目录的length++,和外部表的length++;

my_rm()【删除一个文件】

相比删除目录,少的部分是对于文件内容块的设置,将开的部分设置free属性

  • 读出当前目录块的内容

  • 然后在当前目录块中找到这个文件

  • 通过比对fat表找到文件所占的块数

  • 根据文件的块数将制定的区域释放掉

  • 将上层目录的length--,当前目录的length--,

my_cd()【打开一个目录】

接收目录名,然后打开这个目录,进入目录下面,以后的当前目录就是这个目录了。

  • 调用open函数

  • 判断是否是已经打开(如何判断???)

  • 存在后将其加入到打开列表中,添加一个

  • 调用ls操作,产生当下目录的所有文件

  • 根据文件名找到上层目录,将该层目录关闭。

my_open()【打开】

  • 装载父目录进来

  • 根据名称从父目录的fcb中进行检测判断是否存在

  • 在当前打开列表中进行检测,如果可以的话分配一个块出去。

  • 将fcb中的内容拷贝给打开列表中的一项

根据传递的FD找到制定的块区域,根据制定的长度进行读写操作。

my_read()【读文件】

  • 根据传递进来的fd将我们的文件读出

my_write()【写文件】

  • 根据传递进来的内容和fd将我们的数据写回到我们的文件中,调用do_write();

// Created by ChenJensen on 16/1/1.
#include <stdio.h>
#include <sys/malloc.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

using namespace std;

#define BLOCKSIZE 1024
#define SIZE 1024000
#define END 65535
#define FREE 0
#define ROOTBLOCKNUM 2
#define MAXOPENFILE 10
#define FILENAME "/Users/chenjensen/Desktop/myfsys"
#define MODE "r"

typedef struct FCB
{
    unsigned char attribute;// 暂时只有两种属性,0:目录文件;1:数据文件
    unsigned short time;
    unsigned short data;
    unsigned short first;//该fcb块指向的第一块区域
    unsigned long length;//长度,目录项
    short  free;// 标示目录项是否为空,0为空,1为已分配
    char filename[8];//文件名
    char exname[4];//后缀名

}fcb;

//Fat表其中表示的指向下一个地址,如果没有则标记为end,没有占有的时候标记为free
typedef struct FAT
{
    unsigned short id;
}fat;

//当前打开目录项结构体,包含了fcb块,然后还有
typedef struct USEROPEN
{
    char filename[8];
    char exname[4];
    unsigned char attribute;// 暂时只有两种属性,0:目录文件;1:数据文件
    unsigned short time;
    unsigned short data;
    unsigned short first;
    unsigned long length;
    short free;
    
    int dirno;// 相应打开文件所在的目录项在父目录文件中的盘块号
    int diroff;// 相应打开文件的目录项在父目录文件的dirno盘块中的目录项序号
    int count;//读写指针在文件中的位置
    char dir[80];//相应打开文件所在的目录名
    short fcbstate;// 是否修改了文件的FCB的内容,1:修改;0:未修改
    short topenfile;// 标示该用户打开表项是否为空,0:空;1:已分配
}useropen;

typedef struct BLOCK0
{
    char information[200];
    unsigned short root;// 根目录文件的起始盘块号
    unsigned char *startblock;
}block0;

unsigned char *myvhard;
useropen openfilelist[MAXOPENFILE];
useropen *ptrcurdir;// 指向用户打开文件表中的当前目录所在打开文件表项的位置
char currentdir[80];
unsigned char *startp;// 虚拟磁盘上数据区开始的位置

void startsys();
void my_format();
void my_cd(char *dirname);
int my_open(char *filename);
int do_read(int fd,int len,char *text);
void my_close(int fd);
void my_mkdir(char *
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值