我正在尝试实现一个FUSE文件系统,并在阅读后。我想我已经找到了如何实现它。我会说明我对实施的想法。如果对或错,请告诉我。
一个实现文件系统需要使用你认为合适的任何函数实现的操作(例如xmp_getattributes
用于getattr
函数),然后将这些函数映射到fuse_operations类型的结构中的相应函数
static struct fuse_operations xmp_oper =
{
.getattr = xmp_getattributes,
//more declarations...
};
现在,如果我使用类ExFuse
来实现FUSE文件系统,我有一个方法ExFuse::getAttributes
在实现中完成getattr
的工作。然后,我的声明将改为
static struct fuse_operations xmp_oper =
{
.getattr = ExFuse::getAttributes,
//more declarations...
};
我对么?另外,有没有其他方法在C ++中实现FUSE,这比static struct
声明更好?
如果我使用类
ExFuse
来实现FUSE文件系统,我有一个方法ExFuse::getAttributes
,它在实现中完成了getattr
的工作。然后,我的声明将改为
static struct fuse_operations xmp_oper =
{
.getattr = ExFuse::getAttributes,
//more declarations...
};
这是错的。 FUSE需要一个指向函数的指针,但是ExFuse::getAttributes
是一个指向成员方法的指针(因为你没有明确说它是一个静态方法,我只能假设它是一个成员方法)。 They are not the same thing.
您需要使用普通函数或静态方法。
有没有其他方法在C ++中实现FUSE,这比静态结构声明更好?
恐怕不是。 FUSE是用C语言编写的,希望你坚持使用“C方式”。就公共接口而言,这对于使用C ++范例几乎没有余地(当然,只要你不扔,你可以在私有实现中做你想做的事,但这对你没有帮助你把接口写到FUSE)。
上面也已经说过,你班级的所有方法都必须是“静态的”。这是因为当你在C ++中有这样的类时:
class example
{
example ()
int method (int i) {cout << i << '\n';}
};
int main (int argc, char **argv)
{
example ex;
ex.method (1);
}
当您调用上面的ex.method(1)时,实际发生的是这个调用:
{NameMangling}method (&ex, 1);
除非“方法”被声明为静态,否则它会在幕后传递“this”指针。 FUSE界面的所有原型都是错误的。
您可以在FUSE中使用C ++,但使用类来定义结构几乎没有意义。你可以自由地使用向量,字符串等 - 但是考虑使用C ++的头脑(如果你正确地使用它也不会是任何东西) - 但除非你熟悉C ++ - > C的翻译(在过去的糟糕时期,C ++基本上是一个C预处理器,尽可能地坚持使用C语义。
免责声明:我没有测试以下答案中的任何假设
根据@ user6269400,使用C ++类方法进行FUSE操作的主要问题是指向的this
指针 - 或者更重要的是,我们如何在正确的上下文中调用实现FUSE操作的类方法,即作为方法调用C ++类实例。
一个简单的答案是使用FUSE context's private_data
field存储指向实例的指针,然后使用一些粘合代码将其强制转换为类类型。
实现(某些)C ++ FUSE实现的粘合代码的“库”(我在这里使用非常松散的术语)可以在这里找到:https://github.com/jachappell/Fusepp。它的工作方式是将正确命名的非静态类方法挂钩到FUSE操作表,然后使用类实例地址作为“private_data
”初始化FUSE。正如@syam所暗示的,这样做会让FUSE用不正确的(可能是null
)this
地址调用你的类方法,结果将是一个非常不愉快的C ++代码。 Fusepp尝试通过提供this_()
方法来解决这个问题,该方法为您执行上述转换,因此您的代码可能如下所示:
const bool ExFuse::resolve_path(const std::string &path, struct stat* stbuf) {
// ...
}
int ExFuse::getattr(const char *path, struct stat *stbuf, struct fuse_file_info *)
{
memset(stbuf, 0, sizeof(struct stat));
if (!this_()->resolve_path(stbuf))
return -ENOENT;
return 0;
}
所以你必须使用this_()
来访问你的实例成员,并且没有隐含的this
- 如果你试图直接调用resolve_path()
(没有通过this_()
去除)你将得到未定义的行为(最多将是一个分段错误)。
我们很清楚 - 我不推荐使用FusePP:结果代码不是C ++,但看起来与C ++相似,可能会使编译器和人类陷入灾难性的后果。但是采用相同的方法并使用更多的粘合代码来拦截FUSE操作调用,将上下文private_data
强制转换为类实例指针,然后通过实例指针调用C ++方法将非常可行,我相信。