您的位置:首页 > 其它

ceph存储 FUSE API 的两种使用方法

2015-04-02 14:54 716 查看
FUSE 虚拟文件系统集成到我们的应用程序时,有两种使用策略,一种是使用比较上层的API,

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

 

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

 

[cpp]
view plaincopyprint?

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,  
};  

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, 比如下面的代码所示 :

[c-sharp]
view plaincopyprint?

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,  
};  

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,
};
 

 

 

具体的使用方法如下 :

 

[c-sharp]
view plaincopyprint?

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);;  

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的实现,供大家参考。

 

[c-sharp]
view plaincopyprint?

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);  
    }  
}  

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。

 

这两个地方时很关键的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: