linux下简单模拟文件系统

整体思路:文件系统基于一个大文件实现 大文件数据分为几个区域来模拟简单的文件系统 1.User:username and password 2.SuperBlock:blockSize,blockNum,inodeNum,blockFree 3.blockBitmap:the use state of block area 4.inodeBitmap:the use state of in
摘要由CSDN通过智能技术生成

整体思路:

文件系统基于一个大文件实现
大文件数据分为几个区域来模拟简单的文件系统
1.User:username and password
2.SuperBlock:blockSize,blockNum,inodeNum,blockFree
3.blockBitmap:the use state of block area
4.inodeBitmap:the use state of inode area
5.Inode area:inode * inodeMax(blockNum)
6.Block area:block * blockNum

系统评估:

系统的实现只是很基础的,许多实现细节还有优化的空间,还有一些功能可继续扩展。
待优化:
文件读写具体实现写法;
文件写入的方式;
可扩展:
cd命令任意性;
文件移动;
文件复制;
多用户;
图形化支持;
已实现:
基于标准输入输出流读写;
大文件存储,最多支持二级索引,文件大小上限为64M;
子目录和父目录跳转;
文件重命名;
文件,目录删除;
文件,目录读写权限控制;

code:

FileSystem.h 文件系统定义

#ifndef FILESYSTEM_H
#define FILESYSTEM_H

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <malloc.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>

#define BLOCK_SIZE 1024
#define BLOCK_NUM 102400
#define SYSTEM_NAME "FileSystem.tzh"

#define SUDO     0
#define HELP     1
#define LS       2
#define CD       3
#define MKDIR    4
#define TOUCH    5
#define CAT      6
#define WRITE    7
#define RM       8
#define MV       9
#define CP      10
#define CHMOD   11
#define LOGOUT  12
#define EXIT    13
#define SYSINFO 14
#define CLEAR   15
#define ACCOUNT 16

using namespace std;

/**
文件系统块结构
*/
typedef struct{
    unsigned short blockSize;//2B,文件块大小
    unsigned int blockNum;//4B,文件块数量
    unsigned int inodeNum;//4B,i节点数量,即文件数量
    unsigned int blockFree;//4B,空闲块数量
}SuperBlock;


/**
文件i节点结构
100B
*/
typedef struct{
    unsigned int id;      //4B,i节点索引
    char name[30];        //30B,文件名,最大长度29
    unsigned char isDir;  //1B,文件类型 0-file 1-dir
    unsigned int parent;  //4B,父目录i节点索引
    unsigned int length;  //4B,文件长度,unsigned int最大2^32-1(4GB-1B),目录文件则为子文件项数量
    unsigned char type;   //1B,文件权限,0-read-only,1-read-write
    time_t time;          //8B,文件最后修改时间,从1970年1月1日00时00分00秒至今所经过的秒数
    unsigned int addr[12];//12*4B,文件内容索引,文件前10项为直接索引,目录前11项为直接索引
    unsigned int blockId;  //文件项所在的目录数据块的id,便于删除时定位
}Inode,*PInode;


/**
文件部分信息节点,用于简要显示文件信息
文件名 文件/目录 文件长度 文件权限 修改时间
*/
typedef struct {
    unsigned int id;     //4B
    char name[30];       //30B
    unsigned char isDir; //1B
    unsigned int blockId; //4B,在目录数据块中的位置0-255
}Fcb,*PFcb;

typedef struct FCB_LINK_NODE{
    Fcb fcb;
    struct FCB_LINK_NODE* next;
}FcbLinkNode, *FcbLink;

/**
文件系统用户结构
*/
typedef struct{
    char username[10];//用户名,最大长度9
    char password[10];//密码,最大长度9
}User;



class FileSystem
{
    public:
        FileSystem(char* name);
        virtual ~FileSystem();

        int init();
        //system init
        void createFileSystem();
        void openFileSystem();

        //command
        void help();
        void ls();
        void ls_l();
        int cd(char* name);
        //file operation
        int createFile(char* name, unsigned char isDir);
        int read(char* name);
        int write(char* name);
        int del(char* name);
        int mv(char* name, char* newName);
        int cp(char* src, char* dst);
        int chmod(char* name, unsigned char type);
        //system

        void login();
        void logout();
        void exit();
        void systemInfo();
        void clr();
        int account();

        void command(void);


    protected:
    private:
        const int blockSize;//文件块大小
        const int blockNum; //文件块数量
        unsigned char* blockBitmap;//文件块使用图
        unsigned char* inodeBitmap;//i节点使用图
        //大小
        unsigned short userSize;
        unsigned short superBlockSize;
        unsigned short blockBitmapSize;
        unsigned short inodeBitmapSize;
        unsigned short inodeSize;
        unsigned short fcbSize;
        unsigned short itemSize;
        //偏移
        unsigned long sOffset;     //superBlock偏移
        unsigned long bbOffset;    //blockBitmap偏移
        unsigned long ibOffset;    //inodeBitmap偏移
        unsigned long iOffset;     //i节点区偏移
        unsigned long bOffset;     //数据区偏移
        unsigned char isAlive;     //系统是否在运行

        char name[30];//文件系统名
        FILE* fp;//文件系统文件指针
        SuperBlock superBlock;//文件系统块信息
        string curPath;//当前目录字符串
        Inode curInode;//当前目录i节点
        FcbLink curLink;//当前目录子文件链指针


        User user;//用户
        char cmd[5][20];//命令行输入
        char* SYS_CMD[17];//系统支持的命令

        //user区域操作
        void getUser(User* pUser);
        void setUser(User user);


        //superBlock区域操作
        void getSuperBlock(SuperBlock* pSuper);
        void updateSuperBlock(SuperBlock super);

        //blockBitmap区域操作
        unsigned int getAvailableBlockId();
        void getBlockBitmap(unsigned char* bitmap);
        void updateBlockBitmap(unsigned char* bitmap, unsigned int index);
        void updateBlockBitmap(unsigned char* bitmap, unsigned int start, unsigned int count);

        //inodeBitmap区域操作
        unsigned int getAvailableInodeId();
        void getInodeBitmap(unsigned char* bitmap);
        void updateInodeBitmap(unsigned char* bitmap, unsigned int index);
        void updateInodeBitmap(unsigned char* bitmap, unsigned int start, unsigned int count);

        //inode block区域操作
        void getInode(PInode pInode, unsigned int id);
        void updateInode(Inode inode);
        void releaseInode(unsigned int id);

        //data block区域操作
        //地址或文件项
        unsigned int getAvailableFileItem(Inode& inode, unsigned int* availableIndex);
        unsigned int getItem(unsigned int blockId, unsigned int index);
        void updateItem(unsigned int blockId, unsigned int index, unsigned int value);
        void releaseItem(unsigned int blockId, unsigned int id);

        //文件内容
        int getData(unsigned int blockId, char* buff, unsigned int size, unsigned int offset);
        int writeData(unsigned int blockId, char* buff, unsigned int size, unsigned int offset);
        void releaseBlock(unsigned int blockId);

        //定位操作
        unsigned int findChildInode(FcbLink curLink, char* name);

        //目录信息链操作
        void getFcbLinkNode(FcbLink pNode, Inode inode);
        void getFcbLink(FcbLink& curLink, Inode inode);
        void appendFcbLinkNode(FcbLink curLink, Inode inode);
        void removeFcbLinkNode(FcbLink curLink, Inode inode);
        void removeFcbLinkNode(FcbLink curLink, char* name);
        void releaseFcbLink(FcbLink& curLink);

        //system command
        int analyse(char* str);
        void stopHandle(int sig);
        void updateResource();
        void showPath();

        //util
        void showFileDigest(FcbLink pNode);
        void showFileDetail(PInode pInode);
        unsigned int waitForInput(char* buff, unsigned int limit);



};

#endif // FILESYSTEM_H

FileSystem.cpp 文件系统实现

#include "FileSystem.h"

/**
初始化常量,文件系统名和命令集合
finish
*/
FileSystem::FileSystem(char* name)
:blockSize(BLOCK_SIZE),
blockNum(BLOCK_NUM),
blockBitmap(new unsigned char[BLOCK_NUM+1]),
inodeBitmap(new unsigned char[BLOCK_NUM+1]),
isAlive(0),
fp(NULL),
curLink(NULL)
{
    userSize = sizeof(User);
    superBlockSize = sizeof(SuperBlock);
    blockBitmapSize = blockNum;
    inodeBitmapSize = blockNum;
    inodeSize = sizeof(Inode);
    fcbSize = sizeof(Fcb);
    itemSize = sizeof(unsigned int);

    sOffset = userSize;
    bbOffset = sOffset+sizeof(SuperBlock);
    ibOffset = bbOffset+blockBitmapSize;
    iOffset = ibOffset+inodeBitmapSize;
    bOffset = iOffset+sizeof(Inode)*blockNum;

    if(name == NULL || strcmp(name, "") == 0)
        strcpy(this->name, SYSTEM_NAME);
    else
        strcpy(this->name, name);

    SYS_CMD[0] = new char[5];
    strcpy(SYS_CMD[0], "sudo");
    SYS_CMD[1] = new char[5];
    strcpy(SYS_CMD[1], "help");
    SYS_CMD[2] = new char[3];
    strcpy(SYS_CMD[2], "ls");
    SYS_CMD[3] = new char[3];
    strcpy(SYS_CMD[3], "cd");
    SYS_CMD[4] = new char[6];
    strcpy(SYS_CMD[4], "mkdir");
    SYS_CMD[5] = new char[6];
    strcpy(SYS_CMD[5], "touch");
    SYS_CMD[6] = new char[4];
    strcpy(SYS_CMD[6], "cat");
    SYS_CMD[7] = new char[6];
    strcpy(SYS_CMD[7], "write");
    SYS_CMD[8] = new char[3];
    strcpy(SYS_CMD[8], "rm");
    SYS_CMD[9] = new char[3];
    strcpy(SYS_CMD[9], "mv");
    SYS_CMD[10] = new char[3];
    strcpy(SYS_CMD[10], "cp");
    SYS_CMD[11] = new char[6];
    strcpy(SYS_CMD[11], "chmod");
    SYS_CMD[12] = new char[7];
    strcpy(SYS_CMD[12], "logout");
    SYS_CMD[13] = new char[5];
    strcpy(SYS_CMD[13], "exit");
    SYS_CMD[14] = new char[8];
    strcpy(SYS_CMD[14], "sysinfo");
    SYS_CMD[15] = new char[6];
    strcpy(SYS_CMD[15], "clear");
    SYS_CMD[16] = new char[8];
    strcpy(SYS_CMD[16], "account");
}

/**
释放动态分配的控件
finish
*/
FileSystem::~FileSystem()
{
    if(blockBitmap != NULL)
    {
        delete blockBitmap;
        blockBitmap = NULL;
    }

    if(inodeBitmap != NULL)
    {
        delete inodeBitmap;
        inodeBitmap = NULL;
    }

    if(SYS_CMD[0] != NULL)
    {
        for (int i = 0; i < 17; i++)
            delete SYS_CMD[i];
        SYS_CMD[0] = NULL;
    }

    if(curLink != NULL)
    {
        releaseFcbLink(curLink);
    }
}

/**
系统初始化,启动系统时调用
finish
*/
int FileSystem::init()
{
    if(isAlive)
        return -1;
    //signal(SIGINT,stopHandle);
    openFileSystem();
    login();
    command();
    return 0;
}

/**
创建文件系统
finish
*/
void FileSystem::createFileSystem()
{
    printf("create file system...\n");

    if ((fp = fopen(name,"wb+"))==NULL)
    {
        printf("open file %s error...\n",name);
        ::exit(-1);
    }

    //init user
    printf("username:");
    fgets(user.username, sizeof(user.username), stdin);
    if(user.username[strlen(user.username)-1] == '\n')
        user.username[strlen(user.username)-1] = '\0';
    system("stty -echo");
    printf("password:");
    fgets(user.password, sizeof(user.password), stdin);
    if(user.password[strlen(user.password)-1] == '\n')
        user.password[strlen(user.password)-1] = '\0';
    system("stty echo");
    printf("\n");
    printf("username:%s\npassword:%s\n", user.username, user.password);
    setUser(user);

    //init superBlock
    superBlock.blockSize = blockSize;
    superBlock.blockNum = blockNum;
    //分配一个给root
    superBlock.inodeNum = 1;
    superBlock.blockFree = blockNum-1;
    updateSuperBlock(superBlock);

    //init two bitmaps
    unsigned long i;
    //分配一个给root
    blockBitmap[0] = 1;
    inodeBitmap[0] = 1;
    for(i = 1; i < blockNum; i++)
    {
        blockBitmap[i] = 0;
        inodeBitmap[i] = 0;
    }
    updateBlockBitmap(blockBitmap, 0, blockBitmapSize);
    updateInodeBitmap(inodeBitmap, 0, inodeBitmapSize);

    //init inode and block
    long len = 0;
    len += (inodeSize+ blockSize) * blockNum;
    for (i = 0; i < len; i++)
    {
        fputc(0, fp);
    }

    //init root dir
    //set root inode info
    curInode.id = 0;
    strcpy(curInode.name, "/");
    curInode.isDir = 1;
    curInode.parent = inodeSize;
    curInode.length = 0;
    curInode.type = 0;
    time(&(curInode.time));
    for(i = 0; i < 12; i++)
        curInode.addr[i] = 0;
    curInode.blockId = 0;
    //write root inode
    updateInode(curInode);
    fflush(fp);
    //get curLink info
    getFcbLink(curLink, curInode);
    //get current path
    curPath = "/";
    printf("create file system %s finish.\n", this->name);

}

/**
打开文件系统,若不存在,则创建
finish
*/
void FileSystem::openFileSystem()
{
    if((fp = fopen(this->name,"rb"))==NULL)
    {
        createFileSystem();
    }
    else
    {
        printf("open file system...\n");
        if ((fp=fopen(this->name,"rb+"))==NULL)
        {
            printf("open file %s error...\n", name);
            ::exit(1);
        }
        rewind(fp);
        //read header
        getUser(&user);
        getSuperBlock(&superBlock);
        getBlockBitmap(blockBitmap);
        getInodeBitmap(inodeBitmap);
        //get current inode
        getInode(&curInode, 0);
        //get curLink info
        getFcbLink(curLink, curInode);
        //get current path
        curPath = "/";
        printf("open file system %s success\n", this->name);
    }
}

/**
显示帮助信息
finish
*/
void FileSystem::help()
{
    printf("command: \n\
    help    ---  show help menu \n\
    sysinfo ---  show system base information \n\
    logout  ---  exit user \n\
    account ---  modify username and password \n\
    clear   ---  clear the screen \n\
    ls      ---  list the digest of the directory's children \n\
    ls -l   ---  list the detail of the directory's children \n\
    cd      ---  change directory \n\
    mkdir   ---  make directory   \n\
    touch   ---  create a new file \n\
    cat     ---  read a file \n\
    write   ---  write something to a file \n\
    rm      ---  delete a directory or a file \n\
    cp      ---  cp a directory file to another directory or file (not finish)\n\
    mv      ---  rename a file or directory \n\
    chmod   ---  change the authorizatino of a directory or a file \n\
    exit    ---  exit this system\n");
}

/**
列出目录下所有文件(目录)名
finish
*/
void FileSystem::ls()
{
    //printf("ls %s\n", curInode.name);
    FcbLink link = curLink->next;
    while(link != NULL)
    {
        showFileDigest(link);
        link = link->next;
    }
}

/**
列出目录下所有文件(目录)的详细信息
finish
*/
void FileSystem::ls_l()
{
    //printf("ls -l %s\n", curInode.name);
    FcbLink link = curLink->next;
    PInode pInode = new Inode();
    while(link != NULL)
    {
        pInode->id = link->fcb.id;
        getInode(pInode, pInode->id);
        showFileDetail(pInode);
        link = link->next;
    }
}

/**
进入目录,暂时只支持进入子目录和返回父目录
finish
*/
int FileSystem::cd(char* name)
{
    //printf("cd from %s to child %s\n", curInode.name, name);
    unsigned int id;
    //回到父目录
    if(strcmp(name, "..") == 0)
    {
        id = curInode.parent;
        if(curInode.id > 0)
        {
            getInode(&curInode, id);
            getFcbLink(curLink, curInode);
            int pos = curPath.rfind('/', curPath.length()-2);
            curPath.erase(pos+1, curPath.length()-1-pos);
        }
        return 0;
    }
    id = findChildInode(curLink, name);
    if(id > 0)
    {
        getInode(&curInode, id);
        getFcbLink(curLink, curInode);
        curPath.append(name);
        curPath.append(1, '/');
        return 0;
    }
    else
    {
        printf("no such file or directory:%s\n", name);
        return -1;
    }
}

/**
创建文件或目录
flag:0-file,1-dir
finish
*/
int FileSystem::createFile(char * name, unsigned char isDir)
{
    if(name == NULL || strcmp(name, "") == 0 || findChildInode(curLink, name) > 0)
    {
        printf("invalid file name:the name is empty,or the file has existed\n");
        return -1;
    }
    //printf("create file %s (isDir=%d) in %s\n", name, isDir, curInode.name);
    unsigned int index;
    unsigned int dirBlockId = getAvailableFileItem(curInode, &index);
    //找到一个可用文件项
    if(dirBlockId > 0 || curInode.id == 0)
    {
        unsigned int blockId = getAvailableBlockId();
        //找到一个空闲数据块
        if(blockId > 0)
        {
            //更新superBlock
            superBlock.blockFree--;
            superBlock.inodeNum++;
            //更新blockBitmap
            blockBitmap[blockId] = 1;
            updateBlockBitmap(blockBitmap, blockId);

            unsigned int id = getAvailableInodeId();
            //创建i节点
            PInode pInode = new Inode();
            pInode->id = id;
            strcpy(pInode->name, name);
            pInode->isDir = isDir;
            pInode->parent = curInode.id;
            pInode->length = 0;
            pInode->type = 1;
            time(&(pInode->time));
            int i;
            pInode->addr[0] = blockId;
            for(i = 1; i < 12; i++)
                pInode->addr[i] = 0;
            pInode->blockId = dirBlockId;
            //写入i节点
            updateInode(*pInode);
            //更新inodeBitmap
            inodeBitmap[id] = 1;
            updateInodeBitmap(inodeBitmap, id);
            //将文件id(i节点索引)写入目录文件
            //printf("%d register in dir %d [%d]\n", id, dirBlockId, index);
            updateItem(dirBlockId, index, id);
            //printf("%d [%d] = %d\n", dirBlockId, index, id);
            //更新目录i节点
            curInode.length++;
            time(&(curInode.time));
            updateInode(curInode);
            //更新curLink
            appendFcbLinkNode(curLink, *pInode);
            delete pInode;
            //printf("create file %s success:id=%d\n", pInode->name, pInode->id);
            return 0;
        }
        else
        {
            printf("storage space is not enough, %d\n", blockId);
            return -1;
        }
    }
    else
    {
        printf("the directory can't append file item, %d\n", dirBlockId);
        return -1;
    }

}

/**
读取文件
finish
*/
int FileSystem::read(char *name)
{
    //printf("read file %s in %s\n", name, curInode.name);
    unsigned int id = findChildInode(curLink, name);
    if(id > 0)
    {
        //读取i节点
        PInode pInode = new Inode();
        getInode(pInode, id);

        if(pInode->isDir == 0)
        {
            unsigned long len = pInode->length;
            //remember to delete it
            char* buff = new char[blockSize+1];
            int i;
            unsigned int blockId;

            //遍历10个直接索引,读取数据块
            for(i = 0; i < 10; i++)
            {
                blockId = pInode->addr[i];
                if(blockId > 0)
                {
                    if(len > blockSize)
                    {
                        len -= getData(blockId, buff, blockSize, 0);
                        printf("%s", buff);
                    }
                    else
                    {
                        len -= getData(blockId, buff, len, 0);
                        printf("%s\n", buff);
                        //read finish
                        delete buff;
                        return 0;
                    }
                }
                else
                {
                    //read finish
  
  • 18
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值