Chinaunix首页 | 论坛 | 博客
  • 博客访问: 200621
  • 博文数量: 55
  • 博客积分: 2330
  • 博客等级: 大尉
  • 技术积分: 504
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-20 22:55
文章分类

全部博文(55)

文章存档

2013年(6)

2012年(7)

2011年(7)

2010年(35)

我的朋友

分类: 服务器与存储

2010-08-16 22:10:54

fuse_operations又是怎么一回事?

对于实现fuse_lowlevel_ops这组接口,没有内核VFS相关知识的开发者是不可能完成的,为了增强fuse的通用性,使更多的用户能够使用fuse开发文件系统,fuse提供了一组更简单的接口fuse_operations,详细说明请参考fuse.h。这组接口的参数跟unix提供的系统调用的参数很类似,开发者更易理解,fuse想开发者屏蔽了底层的相关对象,直接以文件名作为参数,只有开发者按照自己的方式,把这组接口实现就可以,显然这比上面那组接口的实现要简单得多。

int(* 

 )(const char *, struct stat *)

int(* 

 )(const char *, char *, size_t)

int(* 

 )(const char *, mode_t, dev_t)

int(* 

 )(const char *, mode_t)

int(* 

 )(const char *)

int(* 

 )(const char *)

int(* 

 )(const char *, const char *)

int(* 

 )(const char *, const char *)

int(* 

 )(const char *, const char *)

int(* 

 )(const char *, mode_t)

int(* 

 )(const char *, uid_t, gid_t)

int(* 

 )(const char *, off_t)

int(* 

 )(const char *, struct utimbuf *)

int(* 

 )(const char *, struct  *)

int(* 

 )(const char *, char *, size_t, off_t, struct  *)

int(* 

 )(const char *, const char *, size_t, off_t, struct  *)

int(* 

 )(const char *, struct statvfs *)

int(* 

 )(const char *, struct  *)

int(* 

 )(const char *, struct  *)

int(* 

 )(const char *, int, struct  *)

int(* 

 )(const char *, const char *, const char *, size_t, int)

int(* 

 )(const char *, const char *, char *, size_t)

int(* 

 )(const char *, char *, size_t)

int(* 

 )(const char *, const char *)

int(* 

 )(const char *, struct  *)

int(* 

 )(const char *, void *, , off_t, struct  *)

int(* 

 )(const char *, struct  *)

int(* 

 )(const char *, int, struct  *)

void *(* 

 )(struct  *conn)

void(* 

 )(void *)

int(* 

 )(const char *, int)

int(* 

 )(const char *, mode_t, struct  *)

int(* 

 )(const char *, off_t, struct  *)

int(* 

 )(const char *, struct stat *, struct  *)

int(* 

 )(const char *, struct  *, int cmd, struct flock *)

int(* 

 )(const char *, const struct timespec tv[2])

int(* 

 )(const char *, size_t blocksize, uint64_t *idx)

unsigned int 

: 1

unsigned int 

: 31

int(* 

 )(const char *, int cmd, void *arg, struct  *, unsigned int flags, void *data)

int(* 

 )(const char *, struct  *, struct fuse_pollhandle *ph, unsigned *reventsp)

  

提供这组接口,fuse做了什么?

fuse还是实现了一组fuse_lowlevel_ops的接口,在fuse.c

static struct fuse_lowlevel_ops fuse_path_ops = {

    //只列举了部分方法

    .init = fuse_lib_init,

    .destroy = fuse_lib_destroy,

    .lookup = fuse_lib_lookup,

    .forget = fuse_lib_forget,

    .getattr = fuse_lib_getattr,

    .setattr = fuse_lib_setattr,

.access = fuse_lib_access,

.read = fuse_lib_read,

    .readlink = fuse_lib_readlink

};

 

fuse实现的这组接口跟之前的方法不一样,不是什么都不做,它完成了部分工作,主要是文件节点与文件名的转换关系,然后将文件名作为参数,调用用户实现的fuse_operations的接口。

 

fuse_lib_read的实现

int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,

                 off_t off, struct fuse_file_info *fi)

{

fuse_get_context()->private_data = fs->user_data;

//用户实现的方法

    if (fs->op.read)

        return fs->op.read(path, buf, size, off, fi);

    else

        return -ENOSYS;

}

 

static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,

                          off_t off, struct fuse_file_info *fi)

{

    struct fuse *f = req_fuse_prepare(req);

    char *path;

    char *buf;

    int res;

 

    buf = (char *) malloc(size);

    if (buf == NULL) {

        reply_err(req, -ENOMEM);

        return;

    }

 

    res = -ENOENT;

pthread_rwlock_rdlock(&f->tree_lock); //fuse_operations使用了读写锁

//ino获取path

    path = get_path(f, ino);

    if (path != NULL) {

        struct fuse_intr_data d;

        if (f->conf.debug)

            fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",

                    (unsigned long long) fi->fh, (unsigned long) size,

                    (unsigned long long) off);

 

        fuse_prepare_interrupt(f, req, &d);

        res = fuse_fs_read(f->fs, path, buf, size, off, fi); //通过这个方法调用用户实现的方法

        fuse_finish_interrupt(f, req, &d);

        free(path);

    }

    pthread_rwlock_unlock(&f->tree_lock);

 

    if (res >= 0) {

        if (f->conf.debug)

            fprintf(stderr, "   READ[%llu] %u bytes\n",

                    (unsigned long long)fi->fh, res);

        if ((size_t) res > size)

            fprintf(stderr, "fuse: read too many bytes");

        fuse_reply_buf(req, buf, res); //返回结果

    } else

        reply_err(req, res);

 

    free(buf);

 

从上面的代码可以看出,fusefuse_operations这组操作使用的是读写锁,而不是互斥量,这样有利于提升文件系统执行效率。当读写锁是写加锁状态时,在它被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以获得访问权,但是如果线程希望以写模式对此锁加锁,它必须阻塞直到所有的线程释放读锁。在不同的系统上读写锁的实现可能各不相同,但当读写锁处于读模式锁住状态时,如果有另外线程试图以写模式加锁时,读写锁通常会阻塞接下来的读模式锁请求,以避免读模式锁被长期占用,导致写模式锁请求很长时间不能被满足。



原文链接:http://blog.chinaunix.net/u2/87570/showart_2166461.html

阅读(1501) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~