# newfs **Repository Path**: Hmount/newfs ## Basic Information - **Project Name**: newfs - **Description**: 一个基于FUSE的青春版EXT2文件系统 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-12-11 - **Last Updated**: 2024-12-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: C语言, FUSE, 文件系统 ## README # 仓库介绍 这是一个基于FUSE实现青春版EXT2文件系统,仓库中不包含FUSE及ddriver设备的环境,使用前请保证熟悉FUSE和ddriver的使用方法. # 使用手册 当前文件系统支持如下命令: ### 一、mount + 将设备ddrive以newfs文件系统形式,挂载到newfs/tests/mnt目录下 ```shell ./build/newfs --device=/home/students/200110720/ddriver -f -d -s ./tests/mnt/ ``` ### 二、ls + ls命令为英文单词 list 的缩写,其功能是列出指定目录下的内容及其相关属性信息,默认状态下,ls命令会列出当前目录的内容。 ```shell # 语法格式: ls [选项] [文件] ``` ### 三、cd + cd命令为"change directory"的缩写,其功能是切换到某个目录下 ```shell # 语法格式: cd 目录名 ``` ### 四、mkdir + mkdir命令是“make directories”的缩写,用来创建目录 ```shell # 语法格式: mkdir [参数] [目录] ``` ### 五、touch + 使用指令touch时,如果指定的文件不存在,则将创建一个新的空白文件 ```shell # 创建文件 touch [文件名] ``` ### 六、unmount + 卸载tests/mnt目录下的newfs文件系统 ```shell fusermount -u tests/mnt ``` 在本次基于FUSE的青春版EXT2文件系统实验过程中,同学们首先学习了 Linux文件系统基础知识,并顺利编译运行了基于fuse的示例文件系统系统simplefs,并实现了自己的newfs,实现了一些简单的文件系统功能。 在老师和指导书的指导下,同学们通过一些生动形象的示例理解的文件系统的挂载和卸载,这是在理论课上没有涉及的知识。 这之后,我们深入阅读了simplefs的内核源码,认识了文件系统的创建文件/文件夹(数据块可预分配)以及查看文件夹下的文件(读取文件夹内容) 的工作原理,并结合课上所学关于EXT2文件系统的组成结构的相关知识,在自己的newfs文件系统中编写了一些钩子函数,基本实现了ls、touch、mkdir等文件系统命令. 总的来说,本次实践让同学们收获颇丰,通过实践加深了我们对理论课中操作系统文件系统等知识的理解, 为后续其他课程打下坚实的基础。在此对为课程辛勤付出的老师和助 教们表示由衷的感谢,也希望这门课后续能越办越好,为下一届的同学带去更多有用的知识 # 文件系统布局 + 本次实验实现的文件系统newfs采用的是简化版的EXT2文件系统布局 ![fs_layout](layout.jpg) 系统主要包含如下五个部分 ``` superblock :超级块,包含整个系统的总体信息; 索引节点位图 :记录着 索引节点 表的使用情况, 用1个比特 记录某一个索引节点是否被使用; 数据块位图 :记录着 数据块 的使用情况, 用1个比特 记录某一个数据块是否被占用; 索引节点 (inode) :记录着文件的元数据,每个文件都与一个inode对应,但一个inode可能对应多个文件(硬链接)。在 本实验中可以认为一个inode对应一个文件 。 数据块 :记录文件内容. ``` + 基本布局参数 ``` # 每个一级索引下存储6个数据块的指针 # BSIZE => 逻辑块的大小 # Super => 超级块 # Inode Map => Inode位图 # Data Map => 数据块位图 # DATA => 数据区, *代表剩下的区域都是数据区 | BSIZE = 1024 B | | Super(1) | Inode Map(1) | DATA Map(1) | Inodes(582) | DATA(*) | ``` + DDRIVER虚拟磁盘驱动 ``` 本次实验提供了虚拟磁盘接口,头文件ddriver.h中提供了完备的注释。该接口底层实现简单,且基本符合POSIX规范(即与标准write、read、lseek、ioctl等接口保持一致).我们对单次读取、写入的IO大小做出了限制,保证其与磁盘块大小对齐。 DDRIVER驱动 模拟了 对一个容量为4MiB的磁盘 的操作,同样,4MiB可以通过ddriver_ioctl函数访问得到。其中需要注意的是它 保留了磁盘的访问特性 ,即 按块访问 ,每次读写都需要 读写完整的512B 的磁盘块。 ``` + 内存中的文件系统数据结构 ```c struct newfs_inode { int ino; /* 在inode位图中的下标 */ int size; /* 文件已占用空间 */ char target_path[NEWFS_MAX_FILE_NAME]; /* store traget path when it is a symlink */ int dir_cnt; struct newfs_dentry* dentry; /* 指向该inode的dentry */ struct newfs_dentry* dentrys; /* 这个目录下的所有目录项 */ uint8_t* data[6]; // 数据内容 int data_block[6]; // 数据存放在的数据块标号 }; struct newfs_dentry { char fname[NEWFS_MAX_FILE_NAME]; struct newfs_dentry* parent; /* 父亲Inode的dentry */ struct newfs_dentry* brother; /* 兄弟 */ int ino; struct newfs_inode* inode; /* 指向inode */ NEWFS_FILE_TYPE ftype; }; struct newfs_super { int driver_fd; int sz_io; int sz_blk; int sz_disk; int sz_usage; // inode位图 int max_ino; uint8_t* map_inode; int map_inode_blks; int map_inode_offset; // 数据位图 uint8_t* map_data; int map_data_blks; int map_data_offset; // inode开始地址 int inode_offset; // 数据块开始地址 int data_offset; boolean is_mounted; struct newfs_dentry* root_dentry; }; ``` + 磁盘中的文件系统数据结构 由于我们需要从磁盘中读取数据,因此需要定义磁盘中的数据结构方便存取 ```c struct newfs_super_d { uint32_t magic_num; int sz_usage; int max_ino; int map_inode_blks; int map_inode_offset; int map_data_blks; int map_data_offset; // 两种块的开始位置 int inode_offset; int data_offset; }; struct newfs_inode_d { int ino; /* 在inode位图中的下标 */ int size; /* 文件已占用空间 */ char target_path[NEWFS_MAX_FILE_NAME];/* store traget path when it is a symlink */ int dir_cnt; int data_block[6]; // 数据存放在的数据块标号 NEWFS_FILE_TYPE ftype; }; struct newfs_dentry_d { char fname[NEWFS_MAX_FILE_NAME]; NEWFS_FILE_TYPE ftype; int ino; /* 指向的ino号 */ }; ```