Github开源生信云平台 DEMO
/dev/fuse
cat
# vim /etc/ossfs2.conf --oss_endpoint=https://oss-cn-beijing.aliyuncs.com --oss_bucket=*** --oss_access_key_id=**** --oss_access_key_secret=***
docker run --rm -it -v $PWD:$PWD -w $PWD \ --cap-add SYS_ADMIN \ --device /dev/fuse \ --security-opt apparmor:unconfined \ ubuntu bash
ossfs2 mount /opt -c /etc/ossfs2.conf
--device /dev/fuse
--cap-add SYS_ADMIN
下面我用 最清晰、最形象的方式解释 /dev/fuse 的工作原理,并用一个完整的例子说明 FUSE 是如何让“用户态写的代码”变成一个真正可挂载的文件系统。
/dev/fuse 是一个 字符设备,是 FUSE 文件系统在 Linux 中和内核通信的唯一接口。
它的作用是:
允许一个普通用户态程序,实现一个虚拟文件系统,并通过 /dev/fuse 把请求交给内核,由内核挂载到系统中。
换句话说:
这就是 用户态文件系统框架(Filesystem in Userspace)。
流程图:
用户程序(如 ossfs, s3fs, 自定义FS) │ (实现 read, write, getattr, readdir 等逻辑) │ /dev/fuse │ FUSE 内核模块 │ Linux VFS (虚拟文件系统层) │ 应用程序(ls, cat, python)
你写的文件系统逻辑跑在 用户空间,但最终被内核当成正式文件系统看待。
下面是一个典型 最简单的 FUSE 文件系统示例:
当你挂载它时:
ls /mnt/hello
你只会看到一个文件:
hello.txt
内容永远是:
Hello from FUSE!
一个最小可运行的 FUSE 文件系统示例:
#define FUSE_USE_VERSION 26 #include <fuse.h> #include <string.h> static int hello_getattr(const char *path, struct stat *stbuf) { memset(stbuf, 0, sizeof(struct stat)); if (strcmp(path, "/") == 0) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; } else if (strcmp(path, "/hello.txt") == 0) { stbuf->st_mode = S_IFREG | 0444; stbuf->st_nlink = 1; stbuf->st_size = strlen("Hello from FUSE!\n"); } else { return -ENOENT; } return 0; } static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); filler(buf, "hello.txt", NULL, 0); return 0; } static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { const char *hello_str = "Hello from FUSE!\n"; if (strcmp(path, "/hello.txt") != 0) return -ENOENT; size_t len = strlen(hello_str); if (offset < len) { if (offset + size > len) size = len - offset; memcpy(buf, hello_str + offset, size); } else { size = 0; } return size; } static struct fuse_operations hello_ops = { .getattr = hello_getattr, .readdir = hello_readdir, .read = hello_read, }; int main(int argc, char *argv[]) { return fuse_main(argc, argv, &hello_ops, NULL); }
gcc hello.c -o hello_fs `pkg-config fuse --cflags --libs`
mkdir /mnt/hello
./hello_fs /mnt/hello
现在你可以测试文件系统了:
输出:
cat /mnt/hello/hello.txt
cat → Linux 内核 → VFS → FUSE 内核模块 → /dev/fuse → 你的用户态程序 → 返回内容 → 最终显示
也就是说:
👉 hello_read 函数是 cat 的“底层文件系统”
本质就是:
你写的用户态程序 “假装” 是一个文件系统,而 /dev/fuse 是它与内核的桥梁。