基于Fuse的最簡單的文件系統(tǒng)



什么是文件系統(tǒng)
首先我們介紹一下什么是文件系統(tǒng)。
文件系統(tǒng)是一個將硬盤的線性地址轉(zhuǎn)換為層級結(jié)構(gòu)的軟件系統(tǒng),其核心是給用戶呈現(xiàn)層級結(jié)構(gòu)的目錄樹(如下圖所示)。在文件系統(tǒng)中有兩個非常重要的概念,一個是文件,另外一個是目錄(或者文件夾)。其中目錄是一個容器,可以存儲文件或者目錄(稱為子目錄)。文件是存儲數(shù)據(jù)的實體,我們的數(shù)據(jù)都是以文件的形態(tài)進行存儲的。文件有很多種類,比如視頻文件、音頻文件、Word文檔和文本文件等等。


文件系統(tǒng)的API
在普通用戶角度,文件系統(tǒng)提供了一個層級結(jié)構(gòu)的文件組織方式。
從程序開發(fā)的角度,文件系統(tǒng)提供一套API來訪問文件和目錄。比如文件的打開、關(guān)閉、讀取數(shù)據(jù)和寫入數(shù)據(jù)等,目錄的打開、讀?。ū闅v)和關(guān)閉等等,具體如下所示是這些API的一個子集。對于上述API,在內(nèi)核態(tài)都有對應(yīng)的API來實現(xiàn)具體的功能。
理解這些API很重要,因為FUSE正是在內(nèi)核態(tài)對這些API的請求進行了截獲,然后轉(zhuǎn)發(fā)到用戶態(tài)來處理的。
| 功能描述 | Linux API |
|---|---|
| 打開文件 | open |
| 向文件寫數(shù)據(jù) | write |
| 從文件讀數(shù)據(jù) | read |
| 關(guān)閉文件 | close |
| 移動文件指針位置 | lseek |
| 獲取文件屬性 | stat |
| 遍歷目錄 | readdir |

什么是FUSE


實現(xiàn)一個不是文件系統(tǒng)的文件系統(tǒng)


/* 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庫中找到。

發(fā)布:劉恩惠
審核:陳歆懿
如果喜歡本文 歡迎 在看丨留言丨分享至朋友圈 三連 < PAST · 往期回顧 > ![]()
書單 | 3月新書速遞!
評論
圖片
表情

