【问题标题】:Using syscall open() to open a file in FUSE使用系统调用 open() 在 FUSE 中打开文件
【发布时间】:2020-10-21 16:34:14
【问题描述】:

我最近正在研究 fuse,但由于我对 linux 中的文件系统知之甚少,因此仍然无法掌握它的工作原理。最令人困惑的事情之一是 如果我使用系统调用 open() 在 fuse_operation "open" 的函数中打开一个文件会发生什么,就像下面的 code

int bb_open(const char *path, struct fuse_file_info *fi)
{
    int retstat = 0;
    int fd;
    char fpath[PATH_MAX];

    bb_fullpath(fpath, path);
    
    log_msg("bb_open(fpath\"%s\", fi=0x%08x)\n",
        fpath,  (int) fi);
    
    fd = open(fpath, fi->flags);
    if (fd < 0)
    retstat = bb_error("bb_open open");
    
    fi->fh = fd;
    log_fi(fi);
    
    return retstat;
}

我的假设是:

  1. 正在打开此文件系统(“myfilesystem”)中的文件,请求最终被 fuse 接受并调用 bb_open()
  2. 当执行到达 "fd = open(fpath, fi->flags)" 时,它将再次 open() 该文件系统中的一个文件,然后返回到第一步,然后是一个循环。

但是在尝试了代码之后,它实际上最终成功地打开了文件,这让我感到困惑。我错过了什么重要的事情吗?希望我能理解这个问题,并提前感谢!


编辑

感谢大家的帮助!但我仍然无法得到 user253751 提到的死锁,我想我应该在这里发布更多细节:

static int hello_getattr(const char *path, struct stat *stbuf,
                         struct fuse_file_info *fi)
{
        (void) fi;
        int res = 0;
        memset(stbuf, 0, sizeof(struct stat));
        if (strcmp(path, "/") == 0) {
                stbuf->st_mode = S_IFDIR | 0755;
                stbuf->st_nlink = 2;
        } else if (strcmp(path+1, "hello") == 0) {
                stbuf->st_mode = S_IFREG | 0444;
                stbuf->st_nlink = 1;
                stbuf->st_size = strlen("hello there");
        } else
                res = -ENOENT;
        return res;
}
static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                         off_t offset, struct fuse_file_info *fi,
                         enum fuse_readdir_flags flags)
{
        (void) offset;
        (void) fi;
        (void) flags;
        if (strcmp(path, "/") != 0)
                return -ENOENT;
        filler(buf, ".", NULL, 0, 0);
        filler(buf, "..", NULL, 0, 0);
        filler(buf, "hello", NULL, 0, 0);
        return 0;
}
static int hello_open(const char *path, struct fuse_file_info *fi)
{
        char* fpath = get_full_path(path);
        int fd = open(fpath,O_RDONLY);
        fi->fh = fd;
        log1(fpath);
        log1("  open\n");
        return 0;
}
static int hello_read(const char *path, char *buf, size_t size, off_t offset,
                      struct fuse_file_info *fi)
{
        char* fpath = get_full_path(path);
        read(fi->fh,buf,size); 
        log1(fpath);
        log1("  read\n");
        return size;
}

基本上我使用 hello_readdir() 将文件名填充到目录中,然后告诉 hello_getattr() 获取文件的一些随机信息。然后我 "tail" 文件五次,这就是我从 log

得到的
/home/P1G3s/WorkSpace/PIT/libfuse-fuse-3.9.2/example/hello  open
/home/P1G3s/WorkSpace/PIT/libfuse-fuse-3.9.2/example/hello  read
/home/P1G3s/WorkSpace/PIT/libfuse-fuse-3.9.2/example/hello  open
/home/P1G3s/WorkSpace/PIT/libfuse-fuse-3.9.2/example/hello  open
/home/P1G3s/WorkSpace/PIT/libfuse-fuse-3.9.2/example/hello  open

我认为它不应该打开一个不存在的文件,但似乎 open() 运行良好并且没有发生死锁,但是在第一个尾部之后读取不会显示。

【问题讨论】:

  • bb_fullpath 生成的路径是否在 FUSE 文件系统的挂载点之外?
  • path 和 fpath 的一些示例值是什么?
  • 另外,您对open() 的使用不正确。如果open() 调用可以创建文件,则需要第三个参数来指定创建文件的初始权限。
  • 哦,是的,我觉得我创建文件的方式有点奇怪,我用libfuse的例子“hello”做的方法,文件是通过readdir操作下的filler()添加的,这是否意味着打开的文件只是一个名称?
  • @Ian Abbott 对不起,我没有使用 bb_fullpath(),我只是手动输入路径,文件就在挂载点的正下方。我尝试了相对路径和绝对路径,在这两种情况下都成功打开了文件。我正在使用python打开文件,它似乎打开了文件。

标签: c filesystems system-calls fuse


【解决方案1】:

如果您尝试在您自己的 FUSE 文件系统中打开一个文件,这将造成死锁,因为 open 正在等待您的 FUSE 文件系统完成处理 last open 请求,然后才发送下一个,但您的 FUSE 文件系统在完成该请求之前正在等待 open 完成。

但是,如果您打开另一个不在 FUSE 文件系统中的文件,则没有问题。你open不同的文件,处理完其他程序的打开请求,然后open在其他程序中返回。这只是递归。

【讨论】:

  • 谢谢大佬的回复,所以是死锁而不是循环?这是否意味着我为 fuse_operation 定义的 bb_open 与 fuse 创建的文件系统下的系统调用 open() 不同?
  • @HolyCheeses 我不明白这个问题,但 bb_open 不是系统调用
  • 我假设 bb_open() 被定义为一个 fuse_operation “open”,它仅在创建的文件系统熔断器下充当系统调用 open(),我的假设是否正确?
  • @HolyCheeses 系统调用“open”是系统调用“open”。系统调用代码检查路径是否在 FUSE 文件系统上,如果是,则向 FUSE 服务器进程发送一条消息,其中显示“嘿,有人刚刚在你的一个文件上调用了‘open’,我应该告诉什么他们?”并等待回复。
  • 哦,我想我明白了,然后 FUSE 告诉它执行 bb_open(),但是直到 bb_open() 中的 open() 才被阻塞,因为最后一个 open() 不是完成了。所以 bb_open() 实际上是 open() 的一部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-19
  • 2014-12-21
  • 2010-10-10
  • 2013-08-09
  • 1970-01-01
  • 2015-04-20
  • 2015-06-02
相关资源
最近更新 更多