FUSE API 的两种使用方法

FUSE 虚拟文件系统集成到我们的应用程序时,有两种使用策略,一种是使用比较上层的API,

主循环我们只能调用 ret = fuse_main (fargc, fargv, &my_handler, NULL) 这个主循环的接口,

 

my_handler我们只取我们关心API属性,如下所示

 

static struct fuse_operations my_handler = { .getattr = xmp_getattr, .opendir = xmp_opendir, .readdir = xmp_readdir, .mkdir = xmp_mkdir, .unlink = xmp_unlink, .rmdir = xmp_rmdir, .rename = xmp_rename, .link = xmp_link, .truncate = xmp_truncate, .create = xmp_create, .open = xmp_open, .read = xmp_read, .write = xmp_write, .flush = xmp_flush, .release = xmp_release, };

 

然后我们自己要来实现上面的各种 xmp_ 开头的函数。

 

 

还有一种是使用  fuse_session_loop 这个比较底层的函数来实现,这个时候我们要实现的API都是一些比较底层

的API, 比如下面的代码所示 :

static struct fuse_lowlevel_ops lowlevel_handler = { .lookup = lowlevel_lookup, .getattr = lowlevel_getattr, .readdir = lowlevel_readdir, .mkdir = lowlevel_mkdir, .rmdir = lowlevel_rmdir, .open = lowlevel_open, .read = lowlevel_read, .write = lowlevel_write, .unlink = lowlevel_unlink, .rename = lowlevel_rename, };

 

 

具体的使用方法如下 :

 

struct fuse_chan *ch; fargc = 3; fargv[0] = g_Config.processName; fargv[1] = g_Config.mountSource; fargv[2] = g_Config.mountPath; struct fuse_args args = FUSE_ARGS_INIT(fargc, fargv); snprintf (buf, sizeof(buf)-1, "umount -l %s", g_Config.mountPath); system(buf); ret = fuse_parse_cmdline(&args, &g_Config.mountPath, NULL, NULL); ch = fuse_mount(g_Config.mountPath, &args); if (ret == -1 || ch == NULL) { fprintf (stderr, "fuse mout fail/n"); exit(1); } struct fuse_session *se; se = fuse_lowlevel_new(&args, &lowlevel_handler, sizeof(lowlevel_handler), NULL); if (se != NULL) { if (fuse_set_signal_handlers(se) != -1) { fuse_session_add_chan(se, ch); ret = fuse_session_loop(se); fuse_remove_signal_handlers(se); fuse_session_remove_chan(ch); } fuse_session_destroy(se); } fuse_unmount(g_Config.mountPath, ch); fuse_opt_free_args(&args);;

 

 

底层的API使用起来相对灵活性大一点,本人推荐使用底层的API。当然了,上层的API使用起来相对简单一点。

 

下面复制了一个具体的底层API的实现,供大家参考。

 

void lowlevel_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { writelog (LOG_DEBUG, "call user function_______%s______fuse_ino_t = %d", __FUNCTION__, ino); if (ino != 2) fuse_reply_err(req, EISDIR); else if ((fi->flags & 3) != O_RDONLY) fuse_reply_err(req, EACCES); else { /* direct_io is supposed to allow partial reads. However, setting * the flag causes read length max at 4096 bytes which leads to * *many* requests, poor performance, and errors. Some resources * like TCP ports are recycled too fast for Linux to cope. */ //fi->direct_io = 1; fuse_reply_open(req, fi); } }

 

另外在使用fuse的时候,要注意的是 struct fuse_file_info *fi 这个结构体数据的填充,

 

其中最关键的是 direct_io 和 nonseekable。

 

具体如下 :

                    fi->fh = socket(PF_INET, SOCK_STREAM, 0);
                    fi->direct_io = 1;
                    fi->nonseekable = 0;

 

设置了direct_io=1 可以提高文件读写的速度,一次IO的大小就不在局限于4K,

设置 nonseekable=0, 上层的应用才可以调用seek函数进行,否则无法seek。

 

这两个地方时很关键的。

 

你可能感兴趣的:(FUSE API 的两种使用方法)