课题作业任务:在内存中开辟一个100M的空间作为磁盘空间,在此上模拟创建一个文件管理系统。
本系统已经实现的相关操作:
所有操作都不支持从根目录索引,即都只能访问当前目录下的文件,不能用/a/b越级访问
1)目录相关操作
列出目录下所有文件:ls
切换目录:cd newdir
显示目录:pwd
创建目录:mkdir dirName
删除目录和目录下所有文件:rmdir dirName
修改目录名或文件名:mv oldName newName
2)文件相关操作
创建文件(大小以1KB为单位):touch filename fileSize
删除文件:rm filename
从上一次后读取size字节的文件内容:read fileName size
从头开始读取size字节的文件内容:reread fileName size
从文件尾写入内容:write fileName content
清空文件,从头写入:rewrite fileName content
3)系统操作
使用命令帮助:help
退出系统:quit
全部代码大概有600多行,是一个非常简单的实现,不适合想要深入了解的人观看,网上有其他的功能较为强大实现,代码都在上千,比较具有学习的价值。
点击打开链接(很强大,我自己也还没有仔细看)
点击打开链接(代码好像有点问题)
1. 系统层次结构:
系统接口:是该文件系统提供给用户可以使用的命令接口,如ls,mkdir,touch等
文件管理:是系统对于文件和目录层次的管理的,规定了FCB结构,目录结构等,包含了对接口的实现。
磁盘管理:是系统最底层直接对内存空间的管理,如磁盘空闲空间管理,磁盘空间的分配方式等。
2. 磁盘管理
盘块大小:以1KB的空间作为系统盘块,用以分配的基本单位
分配方式:系统采用连续分配的方式,在磁盘上划定要求的连续盘块分配给文件使用
空间管理:系统采用位示图的方法,标记了磁盘上所有盘块的使用情况。
使用systemStartAddr标记了整个系统的起始地址,以1KB作为盘块划分,所以本系统共有100K个盘块。位示图用char[]表示,所以位示图大小为100KB。位示图存储在系统起始位置,在系统初始化时,0~99号盘块默认被存储位示图使用。
磁盘向文件管理提供的接口说明:
DiskOperate.h#ifndef DISKOPERATE_H_INCLUDED
#define DISKOPERATE_H_INCLUDED
//磁盘操作接口
#define system_size 100*1024*1024 //系统大小
#define block_szie 1024 //盘块大小
#define block_count system_size/block_szie //系统盘块数目
//初始化系统
void initSystem();
//磁盘分配
int getBlock(int blockSize) ;
//获得盘块的物理地址
char* getBlockAddr(int blockNum);
//获得物理地址的盘块号
int getAddrBlock(char* addr);
//释放盘块、
int releaseBlock(int blockNum, int blockSize);
//退出系统
void exitSystem();
#endif // DISKOPERATE_H_INCLUDED
3.文件层次管理说明
//目录项结构:
struct dirUnit{
char fileName[59]; //文件名
char type; //文件类型,0目录, 1文件
int startBlock; //FCB起始盘块
};
//一个目录项包含了文件名和文件类型,当文件为目录时,起始盘块指示了目录表所在的盘块号,当文件为文件时,起始盘块指示了FCB所在的盘块号。
#define dirTable_max_size 15 //目录表项最大值
//目录表结构:
struct dirTable {
int dirUnitAmount;//目录项数目
dirUnit dirs[dirTable_max_size];//目录项列表
};
/*
本系统规定一个目录表只占用一个盘块,一个目录项大小为64B,所以一个目录表中最多可含15个目录项,dirUnitAmount记录每个目录表中已含有的目录项数目。系统在初始化时,会自动生成一个空的根目录表存放于磁盘中,作为用户的初始位置,用户所有的目录和文件都这个表为根进行树状目录结构的展开。
当创建一个目录表时,系统会自动为目录表加上一项名为”..”的目录项,指示父目录表的位置。
*/
//FCB结构:
struct FCB {
int blockNum; //文件数据起始盘块号
int fileSize; //文件大小,盘块为单位
int dataSize; //已写入的内容大小,字节为单位
int readptr; //读指针,字节为单位
int link; //文件链接数
};
/*
文件控制块包含了文件数据的起始位置和大小。dataSize,readptr是为文件的读写操作而准备的,记录文件已写入的内容长度(不可超过文件大小),和当前读取的位置。Link记录了文件的链接数,用于文件的共享,当文件的链接数为0时,系统可以回收文件的空间。同样的,一个FCB大小为20B,但也用一个盘块保存。
由于采用的是连续分配方式,所以系统规定文件被创建时,必须给出文件的大小,而且后期也不能修改文件的大小。
*/
看到这里,如果你有修过计算机系统的话,你就会发现我采取了一种最简单的实现方式,都说了十分简易嘛~~
系统用char[]数组作为位示图保存了每一个盘块的使用状态,而且采取了连续分配的方式,对于目录表和FCB都规定直接使用一个盘块,文件又是规定好大小不能扩展的,所以实现起来减少了很多FAT,索引表,那些离散分配所需的连接方式,单纯练手的话,还是十分简易的。
具体实现
1. 磁盘管理的实现
这部分比较简单,代码备注也很详细了,可以直接看代码
DiskOperate.cpp
#include"DiskOperate.h"
#include<stdio.h>
#include<stdlib.h>
char* systemStartAddr; //系统起始地址
//初始化系统
void initSystem()
{
//创建空间
systemStartAddr = (char*)malloc(system_size * sizeof(char));
//初始化盘块的位示图
for(int i=0; i<block_count; i++)
systemStartAddr[i] = '0';
//用于存放位示图的空间已被占用
int bitMapSize = block_count * sizeof(char) / block_szie;//位示图占用盘块数:100
for(int i=0; i<bitMapSize; i++)//从零开始分配
systemStartAddr[i] = '1'; //盘块已被使用
}
//退出系统
void exitSystem()
{
free(systemStartAddr);
}
//磁盘分配
int getBlock