FUSE用户空间文件系统

Filesystem in Userspace,是Linux 中用于挂载某些网络空间,如SSH,到本地文件系统的模块,在SourceForge上可以找到相关内容(http://sourceforge.net/

//FUSE和内核的通信过程
                   +----------------+
                   | myfs /tmp/fuse |
                   +----------------+
                          |   ^
+--------------+          v   |
| ls /tmp/fuse |    +--------------+
+--------------+    |    libfuse   |
      ^  |          +--------------+
      |  v                |   |
+--------------+    +--------------+
|     glibc    |    |     glibc    |
+--------------+    +--------------+
      ^  |                |   ^
~.~.~.|.~|~.~.~.~.~.~.~.~.|.~.|.~.~.~.~.~.~.~.~.
      |  v                v   |
+--------------+    +--------------+
|              |----|     FUSE     |
|              |    +--------------+
|      VFS     |           ...
|              |    +--------------+
|              |----|     Ext3     |
+--------------+    +--------------+

优点:

  1. 在用户空间实现,开发和调试都比较方便
  2. 可以把一些常用的服务以文件系统的形式展现,方便操作,如ftpfs,sshfs,mailfs等
  3. 可以避免一些版权问题,如linux上对ntfs,zfs的操作都是通过FUSE实现的

缺点:多次在用户态/内核态切换带来的性能下降

//编译方法
# gcc -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26  //FUSE_USE_VERSION分不同的版本

//详见/usr/include/fuse/fuse.h
/*
   This header is for compatibility with older software using FUSE.

   Please use 'pkg-config --cflags fuse' to set include path.  The
   correct usage is still '#include <fuse.h>', not '#include
   <fuse/fuse.h>'.
*/

#include "fuse/fuse.h"
# ./a.out ./test/   //选择一个挂载点
# ls test/
hello
struct fuse_operations
{
    int (*getattr) (const char *, struct stat *);
    int (*open) (const char *, struct fuse_file_info *);
    int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
    int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
    ...
};
/*
  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.

  gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello
*/

#define FUSE_USE_VERSION 26

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

static const char *hello_str = "Hello World!\n";
static const char *hello_path = "/hello";

static int hello_getattr(const char *path, struct stat *stbuf)
{
    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, hello_path) == 0) {
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = strlen(hello_str);
    } 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)
{
    (void) offset;
    (void) fi;

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

    filler(buf, ".", NULL, 0);
    filler(buf, "..", NULL, 0);
    filler(buf, hello_path + 1, NULL, 0);

    return 0;
}

static int hello_open(const char *path, struct fuse_file_info *fi)
{
    if (strcmp(path, hello_path) != 0)
        return -ENOENT;

    if ((fi->flags & 3) != 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, hello_path) != 0)
        return -ENOENT;

    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_oper = {
    .getattr    = hello_getattr,
    .readdir    = hello_readdir,
    .open       = hello_open,
    .read       = hello_read,
};

int main(int argc, char *argv[])
{
    return fuse_main(argc, argv, &hello_oper, NULL);
}

根据不同的错误类型返回不同的值(errno.h)

//卸载文件系统
# fusermounu -uz ./test/

实现ls命令:readdir和getattr
实现touch命令:open和mknod
实现读写文件:read和write

常用参数:

-o allow_other         allow access to other users   
-o auto_unmount        auto unmount on process termination
-o nonempty            allow mounts over non-empty file/dir
-o default_permissions enable permission checking by kernel   
-o fsname=NAME         set filesystem name
-o subtype=NAME        set filesystem type  
-o large_read          issue large read requests (2.4 only)  
-o max_read=N          set maximum size of read requests

允许其他用户
比如文件系统是以root用户挂载的,允许其他任何用户读写挂载目录,而不会去限制权限
配置fuse.conf

# vi /etc/fuse.conf
user_allow_other

应用-o allow_other选项挂载,即可

转载:http://ouonline.net/building-your-own-fs-with-fuse-1

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值