澄清在c ++中实现FUSE文件系统

问题描述 投票:3回答:3

我正在尝试实现一个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声明更好?

c++ fuse
3个回答
4
投票

如果我使用类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)。


1
投票

上面也已经说过,你班级的所有方法都必须是“静态的”。这是因为当你在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语义。


0
投票

免责声明:我没有测试以下答案中的任何假设

根据@ 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用不正确的(可能是nullthis地址调用你的类方法,结果将是一个非常不愉快的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 ++方法将非常可行,我相信。

© www.soinside.com 2019 - 2024. All rights reserved.