使用系统调用 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;
}
我的假设是:
- 正在打开此文件系统(“myfilesystem”)中的文件,请求最终被 fuse 接受并调用 bb_open()。
- 当执行到达 "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。这只是递归。
我最近在研究 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;
}
我的假设是:
- 正在打开此文件系统(“myfilesystem”)中的文件,请求最终被 fuse 接受并调用 bb_open()。
- 当执行到达 "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。这只是递归。