基于Fuse的最简单的文件系统
什么是文件系统
首先我们介绍一下什么是文件系统。
文件系统是一个将硬盘的线性地址转换为层级结构的软件系统,其核心是给用户呈现层级结构的目录树(如下图所示)。在文件系统中有两个非常重要的概念,一个是文件,另外一个是目录(或者文件夹)。其中目录是一个容器,可以存储文件或者目录(称为子目录)。文件是存储数据的实体,我们的数据都是以文件的形态进行存储的。文件有很多种类,比如视频文件、音频文件、Word文档和文本文件等等。
在普通用户角度,文件系统提供了一个层级结构的文件组织方式。
从程序开发的角度,文件系统提供一套API来访问文件和目录。比如文件的打开、关闭、读取数据和写入数据等,目录的打开、读取(遍历)和关闭等等,具体如下所示是这些API的一个子集。对于上述API,在内核态都有对应的API来实现具体的功能。
理解这些API很重要,因为FUSE正是在内核态对这些API的请求进行了截获,然后转发到用户态来处理的。
功能描述 | Linux API |
---|---|
打开文件 | open |
向文件写数据 | write |
从文件读数据 | read |
关闭文件 | close |
移动文件指针位置 | lseek |
获取文件属性 | stat |
遍历目录 | readdir |
/* Description: HelloWorld filesystem class implementation
* This class implements the core API that is related to the directory and file.
* In this class, we implement a very simple file system.
*/
#include "helloworldFS.h"
#include <iostream>
#include <string>
// include in one .cpp file
#include "Fuse-impl.h"
using namespace std;
static const string root_path = "/";
static const string hello_str = "Data Storage Zhang!\n";
static const string hello_path = "/helloworld";
static const string dir_path = "/dir";
int HelloWorldFS::getattr(const char *path, struct stat *stbuf, struct fuse_file_info *)
{
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
if (path == root_path) { //根目录的属性
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
} else if (path == hello_path) { //helloworld文件的属性
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = hello_str.length();
} else if (path == dir_path) { //dir目录的属性
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
} else
res = -ENOENT;
return res;
}
int HelloWorldFS::readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t, struct fuse_file_info *, enum fuse_readdir_flags)
{
if (path != root_path)
return -ENOENT;
filler(buf, ".", NULL, 0, FUSE_FILL_DIR_PLUS);
filler(buf, "..", NULL, 0, FUSE_FILL_DIR_PLUS);
filler(buf, hello_path.c_str() + 1, NULL, 0, FUSE_FILL_DIR_PLUS);
filler(buf, dir_path.c_str() + 1, NULL, 0, FUSE_FILL_DIR_PLUS);
return 0;
}
// Hello filesystem class definition
#ifndef __HELLOFS_H_
#define __HELLOFS_H_
#include "Fuse.h"
#include "Fuse-impl.h"
class HelloWorldFS : public Fusepp::Fuse<HelloWorldFS>
{
public:
HelloFS() {}
~HelloFS() {}
static int getattr (const char *, struct stat *, struct fuse_file_info *);
static int readdir(const char *path, void *buf,
fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi,
enum fuse_readdir_flags);
};
#endif
// See FUSE: example/hello.c
#include "helloworldFS.h"
int main(int argc, char *argv[])
{
HelloWorldFS fs;
int status = fs.run(argc, argv);
return status;
}
cmake_minimum_required(VERSION 3.16)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++14 -D_FILE_OFFSET_BITS=64 -D__coverage -I/usr/include/fuse3 -lfuse3 -lpthread")
project(CMakeSunny
VERSION 1.0
DESCRIPTION "A CMake Tutorial"
LANGUAGES CXX)
add_executable(helloworld
helloworld.cpp
helloworldFS.cpp
Fuse.cpp)
target_link_libraries(helloworld -lfuse3)
./helloworld /mnt/test
注:本文配套的源代码可以在github的SunnyZhang-IT/fs-from-zero库中找到。
发布:刘恩惠
审核:陈歆懿
如果喜欢本文 欢迎 在看丨留言丨分享至朋友圈 三连 < PAST · 往期回顾 > 书单 | 3月新书速递!
评论