使用系统调用 open() 在 FUSE 中打开文件

Using syscall open() to open a file in FUSE

我最近在研究 fuse,但仍然无法理解它是如何工作的,因为我对 linux 中的文件系统知之甚少。最令人困惑的事情之一是,如果我使用系统调用 open() 在 fuse_operation“打开” 函数中打开一个文件会发生什么,例如 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 提到的僵局,我想我应该 post 在这里了解更多详情:

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() 运行良好并且没有发生死锁,但是读取不会在第一个尾巴之后出现。

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

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