分类: 服务器与存储
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);
从上面的代码可以看出,fuse对fuse_operations这组操作使用的是读写锁,而不是互斥量,这样有利于提升文件系统执行效率。当读写锁是写加锁状态时,在它被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以获得访问权,但是如果线程希望以写模式对此锁加锁,它必须阻塞直到所有的线程释放读锁。在不同的系统上读写锁的实现可能各不相同,但当读写锁处于读模式锁住状态时,如果有另外线程试图以写模式加锁时,读写锁通常会阻塞接下来的读模式锁请求,以避免读模式锁被长期占用,导致写模式锁请求很长时间不能被满足。
原文链接:http://blog.chinaunix.net/u2/87570/showart_2166461.html