了解Linux文件系統的同學都清楚,Linux的文件系統都是在內核態開發的。內核態開發最大的問題是涉及的內容比價多,調試不太方便。因此,很多應用都不太原因涉及內核態的開發。而fuse解決了文件系統必須在內核態的的難題。 它將文件系統的實現從內核態搬到了用戶態,也就是我們可以在用戶態實現一個文件系統。fuse有很多應用,比如與對象存儲(例如S3等)結合,可以實現通過普通目錄訪問雲對象存儲的方式,簡化應用訪問對象存儲的複雜性。

本號將陸續推出3-5篇文章介紹fuse,今天是第一篇,將介紹fuse的基本原理,及給出一個非常簡單的示常式序。多說無益,我們接下來實際操作一下fuse。軟體安裝

要使用該庫進行用戶態文件系統的開發,必需先安裝。包括軟體包和開發用的頭文件等內容。不同的平台安裝方法略有不同,下面分別介紹一下。

Ubuntu 16.04

sudo apt-get install libfuse2 libfuse-dev

CentOS 6

yum install fuse fuse-devel

本文安裝的是fuse-devel-2.9.4-1.0.4.el6.x86_64版本的,後續示常式序也是該版本的,如果版本不一致在測試時可能略有不同。

fuse基本原理

簡單的理解,fuse實現了一個對文件系統訪問的回調。fuse分為內核態的模塊和用戶態的庫兩部分。其中用戶態的庫為程序開發提供介面,也是我們實際開發時用的介面,我們通過這些介面將請求處理功能註冊到fuse中。內核態模塊是具體的數據流程的功能實現,它截獲文件的訪問請求,然後調用用戶態註冊的函數進行處理。
圖1 fuse處理流程

如圖1所示,其中fuse_user是開發的用戶態的文件系統程序,該程序啟動的時候會將自己開發的介面註冊到fuse中,比如讀寫文件的介面,遍歷目錄的介面等等。

同時,通過該程序在系統某個路徑掛載fuse文件系統,比如/tmp/file_on_fuse_fs。此時如果在該目錄中有相關操作時,請求會經過VFS到fuse的內核模塊(上圖中的步驟1),fuse內核模塊根據請求類型,調用用戶態應用註冊的函數(上圖中步驟2),然後將處理結果通過VFS返回給系統調用(步驟3)。

示例及說明

為了更好的理解如何使用fuse,我們這裡實現一個具體的實例。該實例非常簡單,這裡並不是一個真正的文件系統,也不會訪問磁碟,而是在該文件系統的根目錄中顯示一個固定的文件,也就是Hello-world文件。程序源代碼

#define FUSE_USE_VERSION 26
#include <stdio.h>
#include <fuse.h>

/* 這裡實現了一個遍歷目錄的功能,當用戶在目錄執行ls時,會回調到該函數,我們這裡只是返回一個固定的文件Hello-world。 */
static int test_readdir(const char* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* fi)
{
printf( "tfs_readdir path : %s ", path);

return filler(buf, "Hello-world", NULL, 0);
}

/* 顯示文件屬性 */
static int test_getattr(const char* path, struct stat *stbuf)
{
printf("tfs_getattr path : %s ", path);
if(strcmp(path, "/") == 0)
stbuf->st_mode = 0755 | S_IFDIR;
else
stbuf->st_mode = 0644 | S_IFREG;
return 0;
}

/*這裡是回調函數集合,這裡實現的很簡單*/
static struct fuse_operations tfs_ops = {
.readdir = test_readdir,
.getattr = test_getattr,
};

int main(int argc, char *argv[])
{
int ret = 0;
ret = fuse_main(argc, argv, &tfs_ops, NULL);
return ret;
}

編譯運行編譯也是非常的簡單,將上述內容複製到一個名為main.c文件中,然後執行如下命令:gcc -o fuse_user main.c -D_FILE_OFFSET_BITS=64 -lfuse

假設在/tmp目錄下面有一個file_on_fuse_fs目錄,如果沒有可以手動創建一個。然後執行如下命令可以在該目錄掛載新的文件系統。

./fuse_user /tmp/file_on_fuse_fs

此時實際上已經有一個新的文件系統掛載在/tmp/file_on_fuse_fs目錄下面,可以通過mount命令查看一下。

mount可以看到輸出內容中包含如下內容:fuse_user on /tmp/file_on_fuse_fs type fuse.fuse_user (rw,nosuid,nodev)也可以通過ls命令查看一下這個目錄,比如:ls -alh /tmp/file_on_fuse_fs此時輸出如下:

可以看出正式我們期望的內容,也就是只有一個名為Hello-world的文件。至此,我們基本上了解了fuse的原理和如何基於fuse開發一個用戶態的文件系統。由於fuse庫對操作做了很多封裝,因此實現起來並不複雜。後續我們再深入的介紹,包括fuse在內核中的實現和更為詳細的用戶態實現實例,以期我們對fuse有更加深入的理解。
推薦閱讀:
相关文章