fuse用户态文件系统安装

1 下载FUSE

GitHub地址:https://github.com/libfuse/libfuse
在FUSE的GitHub页面上下载最新Release版本libfuse 3.8.0 https://github.com/libfuse/libfuse/archive/fuse-3.8.0.tar.gz

2 编译安装FUSE

2.1 编译准备工作

推荐使用Meson和ninja来编译安装FUSE。

sudo apt install ninja-build
sudo apt install meson

2.2 Meson预处理

git clone https://github.com/libfuse/libfuse.git
cd libfuse
mkdir build; cd build
meson

可以看到如下输出

sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/build$ meson
The Meson build system
Version: 0.53.2
Source dir: /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse
Build dir: /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/build
Build type: native build
Project name: libfuse3
Project version: 3.9.3
C compiler for the host machine: cc (gcc 9.3.0 "cc (Ubuntu 9.3.0-10ubuntu2) 9.3.0")
C linker for the host machine: cc ld.bfd 2.34
Host machine cpu family: x86_64
Host machine cpu: x86_64
Checking for function "fork" : YES 
Checking for function "fstatat" : YES 
Checking for function "openat" : YES 
Checking for function "readlinkat" : YES 
Checking for function "pipe2" : YES 
Checking for function "splice" : YES 
Checking for function "vmsplice" : YES 
Checking for function "posix_fallocate" : YES 
Checking for function "fdatasync" : YES 
Checking for function "utimensat" : YES 
Checking for function "copy_file_range" : YES 
Checking for function "fallocate" : YES 
Checking for function "setxattr" : YES 
Checking for function "iconv" : YES 
Checking whether type "struct stat" has member "st_atim" : YES 
Checking whether type "struct stat" has member "st_atimespec" : NO 
Configuring config.h using configuration
meson.build:66: WARNING: Consider using the built-in warning_level option instead of using "-Wall".
meson.build:66: WARNING: Consider using the built-in warning_level option instead of using "-Wextra".
meson.build:69: WARNING: Consider using the built-in warning_level option instead of using "-Wall".
meson.build:69: WARNING: Consider using the built-in warning_level option instead of using "-Wextra".
meson.build:69: WARNING: Consider using the built-in option for language standard version instead of using "-std=c++11".
Message: Compiler warns about unused result even when casting to void
Run-time dependency threads found: YES
Library iconv found: NO
Library dl found: YES
Library rt found: YES
Found pkg-config: /usr/bin/pkg-config (0.29.1)
Run-time dependency udev found: YES 245
Program install_helper.sh found: YES (/home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/util/install_helper.sh)
C++ compiler for the host machine: c++ (gcc 9.3.0 "c++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0")
C++ linker for the host machine: c++ ld.bfd 2.34
Build targets in project: 26
Found ninja-1.10.0 at /usr/bin/ninja

2.3 使用Ninja来build,test和 install libfuse

ninja
sudo apt-get install python3-pip
sudo pip3 install pytest  # 安装python3 的pytest模块
sudo python3 -m pytest test/

输出

sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/build$ sudo python3 -m pytest test/
============================================================== test session starts ==============================================================
platform linux -- Python 3.8.2, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/build/test, configfile: pytest.ini
collected 43 items                                                                                                                              

test/test_ctests.py::test_write_cache[False] PASSED                                                                                     [  2%]
test/test_ctests.py::test_write_cache[True] PASSED                                                                                        [  4%]
test/test_ctests.py::test_notify1[True-notify_inval_inode] PASSED                                                                         [  6%]
test/test_ctests.py::test_notify1[True-invalidate_path] PASSED                                                                            [  9%]
test/test_ctests.py::test_notify1[True-notify_store_retrieve] PASSED                                                                      [ 11%]
test/test_ctests.py::test_notify1[False-notify_inval_inode] PASSED                                                                        [ 13%]
test/test_ctests.py::test_notify1[False-invalidate_path] PASSED                                                                           [ 16%]
test/test_ctests.py::test_notify1[False-notify_store_retrieve] PASSED                                                                     [ 18%]
test/test_ctests.py::test_notify_file_size[True] PASSED                                                                                   [ 20%]
test/test_ctests.py::test_notify_file_size[False] PASSED                                                                                  [ 23%]
test/test_examples.py::test_hello[hello-options0-invoke_directly] PASSED                                                                  [ 25%]
test/test_examples.py::test_hello[hello-options0-invoke_mount_fuse] PASSED                                                                [ 27%]
test/test_examples.py::test_hello[hello-options0-invoke_mount_fuse_drop_privileges] PASSED                                                [ 30%]
test/test_examples.py::test_hello[hello-options1-invoke_directly] PASSED                                                                  [ 32%]
test/test_examples.py::test_hello[hello-options1-invoke_mount_fuse] PASSED                                                                [ 34%]
test/test_examples.py::test_hello[hello-options1-invoke_mount_fuse_drop_privileges] PASSED                                                [ 37%]
test/test_examples.py::test_hello[hello_ll-options0-invoke_directly] PASSED                                                               [ 39%]
test/test_examples.py::test_hello[hello_ll-options0-invoke_mount_fuse] PASSED                                                             [ 41%]
test/test_examples.py::test_hello[hello_ll-options0-invoke_mount_fuse_drop_privileges] PASSED                                             [ 44%]
test/test_examples.py::test_hello[hello_ll-options1-invoke_directly] PASSED                                                               [ 46%]
test/test_examples.py::test_hello[hello_ll-options1-invoke_mount_fuse] PASSED                                                             [ 48%]
test/test_examples.py::test_hello[hello_ll-options1-invoke_mount_fuse_drop_privileges] PASSED                                             [ 51%]
test/test_examples.py::test_passthrough[False-passthrough-False] PASSED                                                                   [ 53%]
test/test_examples.py::test_passthrough[False-passthrough-True] SKIPPED                                                                   [ 55%]
test/test_examples.py::test_passthrough[False-passthrough_fh-False] PASSED                                                                [ 58%]
test/test_examples.py::test_passthrough[False-passthrough_fh-True] SKIPPED                                                                [ 60%]
test/test_examples.py::test_passthrough[False-passthrough_ll-False] PASSED                                                                [ 62%]
test/test_examples.py::test_passthrough[False-passthrough_ll-True] PASSED                                                                 [ 65%]
test/test_examples.py::test_passthrough[True-passthrough-False] PASSED                                                                    [ 67%]
test/test_examples.py::test_passthrough[True-passthrough-True] SKIPPED                                                                    [ 69%]
test/test_examples.py::test_passthrough[True-passthrough_fh-False] PASSED                                                                 [ 72%]
test/test_examples.py::test_passthrough[True-passthrough_fh-True] SKIPPED                                                                 [ 74%]
test/test_examples.py::test_passthrough[True-passthrough_ll-False] PASSED                                                                 [ 76%]
test/test_examples.py::test_passthrough[True-passthrough_ll-True] PASSED                                                                  [ 79%]
test/test_examples.py::test_passthrough_hp[False] PASSED                                                                                  [ 81%]
test/test_examples.py::test_passthrough_hp[True] PASSED                                                                                   [ 83%]
test/test_examples.py::test_ioctl PASSED                                                                                                  [ 86%]
test/test_examples.py::test_poll PASSED                                                                                                   [ 88%]
test/test_examples.py::test_null PASSED                                                                                                   [ 90%]
test/test_examples.py::test_notify_inval_entry[True] PASSED                                                                               [ 93%]
test/test_examples.py::test_notify_inval_entry[False] PASSED                                                                              [ 95%]
test/test_examples.py::test_cuse PASSED                                                                                                   [ 97%]
test/test_examples.py::test_printcap PASSED                                                                                               [100%]

=============================================================== warnings summary ================================================================
test/util.py:132
test/util.py:132
  /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/build/test/util.py:132: PytestUnknownMarkWarning: Unknown pytest.mark.uses_fuse - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
    return pytest.mark.uses_fuse()

-- Docs: https://docs.pytest.org/en/stable/warnings.html
============================================================ short test summary info============================================================
SKIPPED [4] test/test_examples.py:126: example does not support writeback caching

最后安装

sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/build$ sudo ninja install
[0/1] Installing files.
Installing lib/libfuse3.so.3.9.3 to /usr/local/lib/x86_64-linux-gnu
Installing util/fusermount3 to /usr/local/bin
Installing util/mount.fuse3 to /usr/local/sbin
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/include/fuse.h to /usr/local/include/fuse3
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/include/fuse_common.h to /usr/local/include/fuse3
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/include/fuse_lowlevel.h to /usr/local/include/fuse3
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/include/fuse_opt.h to /usr/local/include/fuse3
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/include/cuse_lowlevel.h to /usr/local/include/fuse3
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/include/fuse_log.h to /usr/local/include/fuse3
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/doc/fusermount3.1 to /usr/local/share/man/man1
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/doc/mount.fuse3.8 to /usr/local/share/man/man8
Installing /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/build/meson-private/fuse3.pc to /usr/local/lib/x86_64-linux-gnu/pkgconfig
Running custom install script '/home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/util/install_helper.sh /usr/local/etc /usr/local/bin /lib/udev/rules.d true'
update-rc.d: warning: start and stop actions are no longer supported; falling back to defaults
update-rc.d: warning: stop runlevel arguments (0 6) do not match fuse3 Default-Stop values (none)

3 测试hello.c例程文件系统

FUSE的example目录下自带了许多测试文件系统,其中最简单文件系统hello.c使用了high-level API,我们以此来测试FUSE是否安装成功。

源码如下:


/*
  FUSE: Filesystem in Userspace
  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>

  This program can be distributed under the terms of the GNU GPL.
  See the file COPYING.
*/

/** @file
 *
 * minimal example filesystem using high-level API
 *
 * Compile with:
 *
 *     gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -o hello
 *
 * ## Source code ##
 * \include hello.c
 */


#define FUSE_USE_VERSION 31

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <assert.h>

/*
 * Command line options
 *
 * We can't set default values for the char* fields here because
 * fuse_opt_parse would attempt to free() them when the user specifies
 * different values on the command line.
 */
static struct options {
    const char *filename;
    const char *contents;
    int show_help;
} options;

#define OPTION(t, p)                           \
    { t, offsetof(struct options, p), 1 }
static const struct fuse_opt option_spec[] = {
    OPTION("--name=%s", filename),
    OPTION("--contents=%s", contents),
    OPTION("-h", show_help),
    OPTION("--help", show_help),
    FUSE_OPT_END
};

static void *hello_init(struct fuse_conn_info *conn,
            struct fuse_config *cfg)
{
    (void) conn;
    cfg->kernel_cache = 1;
    return NULL;
}

static int hello_getattr(const char *path, struct stat *stbuf,
             struct fuse_file_info *fi)
{
    (void) fi;
    int res = 0;

    memset(stbuf, 0, sizeof(struct stat));
    if (strcmp(path, "/") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    } else if (strcmp(path+1, options.filename) == 0) {
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = strlen(options.contents);
    } else
        res = -ENOENT;

    return res;
}

static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
             off_t offset, struct fuse_file_info *fi,
             enum fuse_readdir_flags flags)
{
    (void) offset;
    (void) fi;
    (void) flags;

    if (strcmp(path, "/") != 0)
        return -ENOENT;

    filler(buf, ".", NULL, 0, 0);
    filler(buf, "..", NULL, 0, 0);
    filler(buf, options.filename, NULL, 0, 0);

    return 0;
}

static int hello_open(const char *path, struct fuse_file_info *fi)
{
    if (strcmp(path+1, options.filename) != 0)
        return -ENOENT;

    if ((fi->flags & O_ACCMODE) != O_RDONLY)
        return -EACCES;

    return 0;
}

static int hello_read(const char *path, char *buf, size_t size, off_t offset,
              struct fuse_file_info *fi)
{
    size_t len;
    (void) fi;
    if(strcmp(path+1, options.filename) != 0)
        return -ENOENT;

    len = strlen(options.contents);
    if (offset < len) {
        if (offset + size > len)
            size = len - offset;
        memcpy(buf, options.contents + offset, size);
    } else
        size = 0;

    return size;
}

static struct fuse_operations hello_oper = {
    .init           = hello_init,
    .getattr    = hello_getattr,
    .readdir    = hello_readdir,
    .open       = hello_open,
    .read       = hello_read,
};

static void show_help(const char *progname)
{
    printf("usage: %s [options] <mountpoint>\n\n", progname);
    printf("File-system specific options:\n"
           "    --name=<s>          Name of the \"hello\" file\n"
           "                        (default: \"hello\")\n"
           "    --contents=<s>      Contents \"hello\" file\n"
           "                        (default \"Hello, World!\\n\")\n"
           "\n");
}

int main(int argc, char *argv[])
{
    int ret;
    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);

    /* Set defaults -- we have to use strdup so that
       fuse_opt_parse can free the defaults if other
       values are specified */
    options.filename = strdup("hello");
    options.contents = strdup("Hello World!\n");

    /* Parse options */
    if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1)
        return 1;

    /* When --help is specified, first print our own file-system
       specific help text, then signal fuse_main to show
       additional help (by adding `--help` to the options again)
       without usage: line (by setting argv[0] to the empty
       string) */
    if (options.show_help) {
        show_help(argv[0]);
        assert(fuse_opt_add_arg(&args, "--help") == 0);
        args.argv[0][0] = '\0';
    }

    ret = fuse_main(args.argc, args.argv, &hello_oper, NULL);
    fuse_opt_free_args(&args);
    return ret;
}

从hello.c的注释中我们可以看到gcc编译方式:

sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/example$ gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -o hello
sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/example$ mkdir hello_test
mkdir: cannot create directory ‘hello_test’: File exists
sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/example$ gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -o hello
sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/example$ mkdir hello_test -p 
sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/example$ ./hello hello_test/
sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/example$ mount |grep hello
/home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/example/hello on /home/rlk/workspace/21cnbao/io-courses/fuse-hello/libfuse/example/hello_test type fuse.hello (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/example$ umount hello_test 
sh@ubuntu:~/workspace/21cnbao/io-courses/fuse-hello/libfuse/example$ mount |grep hello

4 分析hello文件系统
。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值