### 简介
简易Linux文件系统的实现,在现有机器硬盘上开辟100M的硬盘空间,作为设定的硬盘空间。设定块大小固定为1KB,用位图法管理iNode节点和空闲块。
需要实现的命令:
- 展示路径(ls)
- 改变目录(cd)
- 创建目录
- 删除目录
- 创建文件
- 删除文件
- 预览文件
- 复制文件(从主机或者模拟盘双向复制)
命令行中的命令命名并未完全按照Linux的来,不过基本没有影响。
实现分为2块:
- SimDisk最简版
- 多shell+SimDisk
关键数据结构
数据在硬盘上存放顺序 |
超级块(1024K) |
iNode表 |
iNode位图 |
块位图 |
剩余数据块 |
iNode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class iNode { public: unsigned int ino; unsigned short i_mode; unsigned long i_size; unsigned long i_time; unsigned long i_mtime; unsigned long i_atime; unsigned long i_blocks; unsigned short i_uid; unsigned short i_gid; unsigned int i_zone[13]; unsigned short i_count; unsigned short i_nlink; iNode(); iNode(unsigned int no, unsigned long size, unsigned long block,vector<unsigned int> zone); ~iNode(); void printInfo(); };
|
以上是我的iNode类对应的头文件代码,是从Linux的iNode结构中精简了部分得出,需要讲解的也就i_mode,i_mode是一个16位的变量,其中前4位用于表示路径或文件等,后面12位用于表示用户权限(rwxrwxrwx),分为3组每组共4位,第一组是所属用户的权限,第二组是同用户组权限,第三组是其他用户的权限。
SuperBlock
超级块的信息如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include "iNode.h" class superBlock { public: unsigned short inode_num; unsigned short inode_remain; unsigned int block_num; unsigned int block_remain; unsigned int inode_table; unsigned int inodemap_pos; unsigned int bitmap_pos; unsigned short blockSize; unsigned short blockSize_bit; unsigned long long maxBytes; unsigned int first_data_block; unsigned int first_data_block_no; superBlock(); ~superBlock(); void printInfo(); int init(); };
|
超级块存放的是文件系统的内容信息,需要经常更新的也只有inode_remain和block_remain的数目即可
在init函数中写死了iNode数目,init函数如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| int superBlock::init() { this->blockSize = 1024; this->inode_num = 10240; this->inode_remain = 10240; this->block_num = 1024 * 100; this->block_remain = 1024 * 100; this->inode_table = this->blockSize*1; this->inodemap_pos = ceil((this->inode_table + inode_num*sizeof(iNode)) / blockSize) * blockSize; this->bitmap_pos = ceil((inodemap_pos + inode_num/8)/blockSize)*blockSize; this->first_data_block = ceil(ceil(bitmap_pos + block_num / 8) / blockSize) * blockSize; this->first_data_block_no = ceil(first_data_block/blockSize)+1; this->blockSize_bit = 10; this->maxBytes = 1024*1024*10; this->block_remain -= first_data_block_no; return 1; }
|
Dentry
Dentry是在内存中维护的内容,不写入硬盘,通过Dentry的父指针和子链表可以很方便的实现路径查找。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class dentry { public: string fileName; string pathName; iNode inode; vector<unsigned int> block_list; vector<dentry*> child_list; dentry * parent; bool is_dir(); void setParent(dentry *); void addChild(dentry *); void removeChild(dentry *s); void setSubDentry(vector<dentry *> list); void showDentry(vector<string> users); void showItself(const vector<string> &users, string coverName=""); string getPathName(); vector<dir> getDirList(); dentry(); dentry(string fileName,iNode inode); ~dentry(); };
|
总控制类
总控制类中有各类函数的声明和实现,对各种结构进行操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #include "stdafx.h" #include "superBlock.h" #include "iNode.h" #include "dentry.h" #include "User.h" #include <Windows.h> #include <map> #include "toolkit.h"
class FileSystem { public: const static int FOLDER_TYPE = 1; const static int FILE_TYPE = 2; const static int READ_ACCESS = 4; const static int WRITE_ACCESS = 2; const static int EXEC_ACCESS = 1; const static int ACCESS_DENY = -100; HANDLE hMapFile; HANDLE usrMapFile; static const string fileName; User currUser; vector<User> userLists; map<string,int> loginUserLists; superBlock s_block; iNode root; dentry root_dentry; dentry *curr_dentry; int serve(); int parseCmd(string cmd); void outputPrompt(); FileSystem(); ~FileSystem(); private: fstream fileDisk; int init_root_dentry(); int init_user(); int save_user(); int alloc_inode(unsigned long size,iNode &node,bool is_dentry = false); int alloc_blocks(int num, vector<unsigned int> &list); int destroy_inode(int id); int destroy_block(int id); int withdraw_node(iNode node); int read_inode(int ino, iNode &node); int write_inode(iNode &node); int clearBlockContent(vector<unsigned int> list); int auth(string username, string pwd); int generate_token(int u_id); int get_shell_user(); int copy(string from, string to); int newfile(string name, unsigned long size=0); int mkdir(string name); int rd(string filename, bool force=false); int del(string filename); int cat(string filename); int cd(string filename); int ls(string filename=""); int chmod(string filename, int i_mode); vector<string> getUsers(); int findDentryWithName(string name, dentry *&p_dentry, int type = FOLDER_TYPE); int findDentry(vector<string> list, dentry *&p_dentry, char firstChar, int type = FOLDER_TYPE); int InitDentry(dentry& p_dentry); int SaveDentry(dentry& p_dentry); template<typename T> int seekAndGet(unsigned long pos, T &item); template<typename T> int seekAndSave(unsigned long pos, T &item); int readBlockIds(iNode inode, vector<unsigned int> &blocks_list); bool checkAccess(int access_type, iNode node); };
|