美文网首页
Ubuntu 18.04 LTS编译安装FUSE

Ubuntu 18.04 LTS编译安装FUSE

作者: 羽羽羽_e0a2 | 来源:发表于2019-11-09 20:35 被阅读0次

    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。

    apt install ninja-build
    apt install meson
    

    2.2 Meson预处理

    将下载的fuse压缩包解压到/opt/目录(此目录可自定义,推荐/opt/)。创建一个临时的build目录并且在build目录中执行Meson:

    cd /opt/
    tar zxvf libfuse-fuse-3.8.0.tar.gz
    mv libfuse-fuse-3.8.0 libfuse
    cd libfuse
    mkdir build; cd build
    

    成功后会看到以下提示:

    ➜  build meson ..         
    The Meson build system
    Version: 0.45.1
    Source dir: /opt/libfuse
    Build dir: /opt/libfuse/build
    Build type: native build
    Project name: libfuse3
    Native C compiler: cc (gcc 7.4.0 "cc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0")
    Native C++ compiler: c++ (gcc 7.4.0 "c++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0")
    Build machine cpu family: x86_64
    Build 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
    Message: Compiler warns about unused result even when casting to void
    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)
    Native dependency udev found: YES 237
    Program install_helper.sh found: YES (/opt/libfuse/util/install_helper.sh)
    Build targets in project: 26
    Found ninja-1.8.2 at /usr/bin/ninja
    

    2.3 使用Ninja来build,test和 install libfuse

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

    输出结果:

    ➜  build ninja        
    [66/66] Linking target example/passthrough_hp.
    
    ➜  build sudo ninja install
    [0/1] Installing files.
    Installing lib/libfuse3.so.3.8.0 to /usr/local/lib/x86_64-linux-gnu/libfuse3.so.3.8.0
    Installing util/fusermount3 to /usr/local/bin/fusermount3
    Installing util/mount.fuse3 to /usr/local/sbin/mount.fuse3
    Installing fuse.h to /usr/local/include/fuse3
    Installing fuse_common.h to /usr/local/include/fuse3
    Installing fuse_lowlevel.h to /usr/local/include/fuse3
    Installing fuse_opt.h to /usr/local/include/fuse3
    Installing cuse_lowlevel.h to /usr/local/include/fuse3
    Installing fuse_log.h to /usr/local/include/fuse3
    Installing /opt/libfuse/doc/fusermount3.1 to /usr/local/share/man/man1
    Installing /opt/libfuse/doc/mount.fuse3.8 to /usr/local/share/man/man8
    Installing /opt/libfuse/build/meson-private/fuse3.pc to /usr/local/lib/x86_64-linux-gnu/pkgconfig
    Running custom install script '/opt/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是否安装成功。
    hello.c源码如下:

    
    /*
      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编译方式:

    gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -o hello
    

    编译后执行后将hello文件系统挂载到test_dir目录上:

    ➜  example gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -o hello
    ➜  example mkdir test_dir                    
    ➜  example ./hello test_dir                  
    ./hello: error while loading shared libraries: libfuse3.so.3: cannot open shared object file: No such file or directory
    

    出错原因是未配置ldconfig,以下是解决方式:

    1. 在/etc/ld.so.conf.d/目录下新建文件fuse.conf
      vim /etc/ld.so.conf.d/fuse.conf
    2. 写入fuse的安装路径
      /usr/local/lib
    3. 保存退出,执行ldconfig
      ldconfig
      重新挂载
    ➜  example ./hello test_dir   
    ➜  example mount |grep test_dir
    /root/Programming/4_fuse/example/hello on /root/Programming/4_fuse/example/test_dir type fuse.hello (rw,nosuid,nodev,relatime,user_id=0,group_id=0)
    
    

    4 分析hello文件系统

    待续。。。

    相关文章

      网友评论

          本文标题:Ubuntu 18.04 LTS编译安装FUSE

          本文链接:https://www.haomeiwen.com/subject/opwnbctx.html