fuse为开发者提供了两组接口,分别是fuse_lowlevel_ops以及fuse_operations,开发者只需要实现这两组接口的一种即可实现一个用户空间文件系统。
struct fuse_lowlevel_ops的成员如下所示,其中init方法在其它所有方法之前调用,用于初始化文件系统,fuse已经实现,destroy则是在文件系统被卸载时做一些清理工作。用于大多数请求的参数都是fuse_ino_t类型的ino,而文件系统提供给用户的视图是以文件名呈现的,故lookup是实现文件系统的关键,它在parent中查找名字name对应的文件,并返回相应的信息,可使用fuse_reply_entry或fuse_reply_err作为请求的返回。
接口中的方法对于了解过VFS的人应该都不难理解,只要按需实现这些接口,你就可以定制出属于自己的文件系统,这组接口的详细说明见fuse_lowlevel.h。
void(*
init )(void *userdata, struct fuse_conn_info *conn)
void(*
destroy )(void *userdata)
void(*
lookup )(fuse_req_t req, fuse_ino_t parent, const char *name)
void(*
forget )(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup)
void(*
getattr )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(*
setattr )(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi)
void(*
readlink )(fuse_req_t req, fuse_ino_t ino)
void(*
mknod )(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev)
void(*
mkdir )(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
void(*
unlink )(fuse_req_t req, fuse_ino_t parent, const char *name)
void(*
rmdir )(fuse_req_t req, fuse_ino_t parent, const char *name)
void(*
symlink )(fuse_req_t req, const char *link, fuse_ino_t parent, const char *name)
void(*
rename )(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_ino_t newparent, const char *newname)
void(*
link )(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname)
void(*
open )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(*
read )(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
void(*
write )(fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t off, struct fuse_file_info *fi)
void(*
flush )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(*
release )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(*
fsync )(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
void(*
opendir )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(*
readdir )(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
void(*
releasedir )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(*
fsyncdir )(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
void(*
statfs )(fuse_req_t req, fuse_ino_t ino)
void(*
setxattr )(fuse_req_t req, fuse_ino_t ino, const char *name, const char *value, size_t size, int flags)
void(*
getxattr )(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
void(*
listxattr )(fuse_req_t req, fuse_ino_t ino, size_t size)
void(*
removexattr )(fuse_req_t req, fuse_ino_t ino, const char *name)
void(*
access )(fuse_req_t req, fuse_ino_t ino, int mask)
void(*
create )(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, struct fuse_file_info *fi)
void(*
getlk )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock)
void(*
setlk )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock, int sleep)
void(*
bmap )(fuse_req_t req, fuse_ino_t ino, size_t blocksize, uint64_t idx)
void(*
ioctl )(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, struct fuse_file_info *fi, unsigned *flagsp, const void *in_buf, size_t in_bufsz, size_t out_bufszp)
void(*
poll )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct fuse_pollhandle *ph)
用户实现的接口是如何跟这个结构关联起来的?
其实fuse中已经实现了一组接口,在fuse_lowlevel.c中,定义了一个静态的结构数组,该数组的元素为一组(函数,名字)的结构,但没做什么实际的工作,当fuse用户空间的daemon从/fuse/dev中读取到请求之后,它通过请求号来判别各个请求,并调用这里相应的处理函数,如读取到read调用时,会调用do_read进行处理。
static struct {
void (*func)(fuse_req_t, fuse_ino_t, const void *);
const char *name;
} fuse_ll_ops[] = {
//只列举了部分
[FUSE_LOOKUP] = { do_lookup, "LOOKUP" },
[FUSE_OPEN] = { do_open, "OPEN" },
[FUSE_READ] = { do_read, "READ" },
[FUSE_WRITE] = { do_write, "WRITE" },
[FUSE_STATFS] = { do_statfs, "STATFS" },
[FUSE_FLUSH] = { do_flush, "FLUSH" },
[FUSE_INIT] = { do_init, "INIT" },
[FUSE_OPENDIR] = { do_opendir, "OPENDIR" },
[FUSE_READDIR] = { do_readdir, "READDIR" },
[FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" },
[FUSE_DESTROY] = { do_destroy, "DESTROY" }
};
接下来看一下do_read的实现
static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
// 如果用户实现了read操作,则调用用户空间的read,否则以没有实现该调用为错误响应,这里的op就是用户实现文件系统时实现的,并传递给fuse。
if (req->f->op.read) {
struct fuse_file_info fi;
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
fi.fh_old = fi.fh;
req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
} else
fuse_reply_err(req, ENOSYS);
}
从这里的实现可以看出,这些操作是没有加任何锁的,如果开发者需要文件系统锁,需要在实现文件系统时自行考虑。
fuse_operations又是怎么一回事?
对于实现fuse_lowlevel_ops这组接口,没有内核VFS相关知识的开发者是不可能完成的,为了增强fuse的通用性,使更多的用户能够使用fuse开发文件系统,fuse提供了一组更简单的接口fuse_operations,详细说明请参考fuse.h。这组接口的参数跟unix提供的系统调用的参数很类似,开发者更易理解,fuse想开发者屏蔽了底层的相关对象,直接以文件名作为参数,只有开发者按照自己的方式,把这组接口实现就可以,显然这比上面那组接口的实现要简单得多。
int(*
getattr )(const char *, struct stat *)
int(*
readlink )(const char *, char *, size_t)
int(*
mknod )(const char *, mode_t, dev_t)
int(*
mkdir )(const char *, mode_t)
int(*
unlink )(const char *)
int(*
rmdir )(const char *)
int(*
symlink )(const char *, const char *)
int(*
rename )(const char *, const char *)
int(*
link )(const char *, const char *)
int(*
chmod )(const char *, mode_t)
int(*
chown )(const char *, uid_t, gid_t)
int(*
truncate )(const char *, off_t)
int(*
utime )(const char *, struct utimbuf *)
int(*
open )(const char *, struct fuse_file_info *)
int(*
read )(const char *, char *, size_t, off_t, struct fuse_file_info *)
int(*
write )(const char *, const char *, size_t, off_t, struct fuse_file_info *)
int(*
statfs )(const char *, struct statvfs *)
int(*
flush )(const char *, struct fuse_file_info *)
int(*
release )(const char *, struct fuse_file_info *)
int(*
fsync )(const char *, int, struct fuse_file_info *)
int(*
setxattr )(const char *, const char *, const char *, size_t, int)
int(*
getxattr )(const char *, const char *, char *, size_t)
int(*
listxattr )(const char *, char *, size_t)
int(*
removexattr )(const char *, const char *)
int(*
opendir )(const char *, struct fuse_file_info *)
int(*
readdir )(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *)
int(*
releasedir )(const char *, struct fuse_file_info *)
int(*
fsyncdir )(const char *, int, struct fuse_file_info *)
void *(*
init )(struct fuse_conn_info *conn)
void(*
destroy )(void *)
int(*
access )(const char *, int)
int(*
create )(const char *, mode_t, struct fuse_file_info *)
int(*
ftruncate )(const char *, off_t, struct fuse_file_info *)
int(*
fgetattr )(const char *, struct stat *, struct fuse_file_info *)
int(*
lock )(const char *, struct fuse_file_info *, int cmd, struct flock *)
int(*
utimens )(const char *, const struct timespec tv[2])
int(*
bmap )(const char *, size_t blocksize, uint64_t *idx)
unsigned int
flag_nullpath_ok: 1
unsigned int
flag_reserved: 31
int(*
ioctl )(const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data)
int(*
poll )(const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp)
提供这组接口,fuse做了什么?
fuse还是实现了一组fuse_lowlevel_ops的接口,在fuse.c中
static struct fuse_lowlevel_ops fuse_path_ops = {
//只列举了部分方法
.init = fuse_lib_init,
.destroy = fuse_lib_destroy,
.lookup = fuse_lib_lookup,
.forget = fuse_lib_forget,
.getattr = fuse_lib_getattr,
.setattr = fuse_lib_setattr,
.access = fuse_lib_access,
.read = fuse_lib_read,
.readlink = fuse_lib_readlink
};
fuse实现的这组接口跟之前的方法不一样,不是什么都不做,它完成了部分工作,主要是文件节点与文件名的转换关系,然后将文件名作为参数,调用用户实现的fuse_operations的接口。
如fuse_lib_read的实现
int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
off_t off, struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
//用户实现的方法
if (fs->op.read)
return fs->op.read(path, buf, size, off, fi);
else
return -ENOSYS;
}
static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi)
{
struct fuse *f = req_fuse_prepare(req);
char *path;
char *buf;
int res;
buf = (char *) malloc(size);
if (buf == NULL) {
reply_err(req, -ENOMEM);
return;
}
res = -ENOENT;
pthread_rwlock_rdlock(&f->tree_lock); //fuse_operations使用了读写锁
//由ino获取path
path = get_path(f, ino);
if (path != NULL) {
struct fuse_intr_data d;
if (f->conf.debug)
fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",
(unsigned long long) fi->fh, (unsigned long) size,
(unsigned long long) off);
fuse_prepare_interrupt(f, req, &d);
res = fuse_fs_read(f->fs, path, buf, size, off, fi); //通过这个方法调用用户实现的方法
fuse_finish_interrupt(f, req, &d);
free(path);
}
pthread_rwlock_unlock(&f->tree_lock);
if (res >= 0) {
if (f->conf.debug)
fprintf(stderr, " READ[%llu] %u bytes\n",
(unsigned long long)fi->fh, res);
if ((size_t) res > size)
fprintf(stderr, "fuse: read too many bytes");
fuse_reply_buf(req, buf, res); //返回结果
} else
reply_err(req, res);
free(buf);
从上面的代码可以看出,fuse对fuse_operations这组操作使用的是读写锁,而不是互斥量,这样有利于提升文件系统执行效率。当读写锁是写加锁状态时,在它被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以获得访问权,但是如果线程希望以写模式对此锁加锁,它必须阻塞直到所有的线程释放读锁。在不同的系统上读写锁的实现可能各不相同,但当读写锁处于读模式锁住状态时,如果有另外线程试图以写模式加锁时,读写锁通常会阻塞接下来的读模式锁请求,以避免读模式锁被长期占用,导致写模式锁请求很长时间不能被满足。
相关推荐
- `struct fuse_ll_ops`: 结构成员包括一个函数指针`func`和命令名字符串`name`,用于处理内核发送的请求。 #### 五、FUSE模块加载 1. **加载过程**:FUSE内核模块通常通过`insmod`或`modprobe`命令加载,这些命令...
描述中提到的"AVR_atmega_fuse_bit_doctor_recovery.rar"是一个用于恢复或修改AVR ATmega系列微控制器fuse bit的工具或教程。"avr Fuse bit"指的是AVR微控制器中的fuse bits,"avr Hvpp"则涉及到高电压并行编程...
标题"Fuse_Drivers_x64."表明这是一个与64位操作系统兼容的Fuse驱动程序集合。Fuse驱动程序在IT行业中通常指的是能够处理特定硬件或软件功能的设备驱动,特别是那些涉及电源管理、数据传输和系统整合的角色。在64位...
官方例子,深度学习专用,机器学习专用,代码简单,一看就会(dlcv fuse model demo)
图象处理算法,一种基于小波变换的图象融合算法,以函数的形式给出,肯定能用
用户态libfuse提供了必要的编程接口,让开发者能够通过实现`fuse_lowlevel_ops`或`fuse_operations`这两个接口之一来构建用户空间文件系统。这些接口定义了一系列回调函数,用来处理文件系统操作。 **1.2 内核态...
### Littelfuse 501系列快熔保险丝详细解析 #### 一、产品概述 Littelfuse公司的501系列保险丝是一款专为高工作环境温度下的电路提供过电流保护而设计的产品。该系列产品完全符合RoHS标准,无铅、无卤素,并能在...
标题 "Atmel Fuse_FUISE_Lesson_atmel_" 暗示了这是一份关于Atmel微控制器(MCU)的教程,特别是涉及到其Fuse设置的环节。在嵌入式系统,尤其是Atmel的AVR系列微控制器中,Fuse字节是编程时必须了解的关键概念。Fuse...
Mio_FUSE_详细中文说明书MIO FUSE手环分为全天候模式和运动模式。 在全天模式下,Mio FUSE可以追踪记录你日常累计的步数、卡路里、距离和运动目标进程。手环的第一屏显示中,则是显示时间信息,可通过触摸B和C触点,...
本主题“基于FUSE的简单文件系统 完整代码”将深入探讨如何使用FUSE库创建一个基本的用户空间文件系统,并提供了一份完整的代码示例。 FUSE的主要优势在于它的灵活性和易用性。开发者可以通过编写C语言程序,利用...
这个名为“fuse_dwb.rar”的压缩包包含了关于小波变换在图像融合中的实现,具体表现为一个名为“fuse_dwb.m”的MATLAB源代码文件。 小波变换的核心在于它能够将复杂的信号或图像分解成不同频率和位置的组件,这些...
在给定的“fuse_dwb.rar”压缩包中,重点涉及了“图像融合”、“小波融合”以及使用“C++”编程语言实现的“灰度图像融合”相关知识。下面,我们将深入探讨这些概念及其应用。 1. **图像融合**: 图像融合是将两幅...
关键词:图像融合,红外图像,可见光图像,微光图像Basic useful functions(基本功能):* Fuse_laplace 基于laplace金字塔的* Fuse_dwt 基于小波变换,DBSS(2,2)* Fuse_sidwt 基于另一种小波变换,Haar* Fuse_con...
【fuse_ros.rar】这个压缩包文件包含了用于学习和开发基于QT框架的C++应用程序的相关资源,特别是针对MVS工业相机的应用。它提供了多种QT控件的示例代码,包括commbox(组合框)、listview(列表视图)和tree(树形...
FUSE通过一组系统调用(例如`fuse_main`、`fuse_lowlevel`等)与内核交互,允许开发者使用C语言或其他支持系统调用的语言(如Python、Java等)实现文件系统逻辑。FUSE的优点包括易于开发、调试和部署,因为用户空间...
This is a matlab code to fuse two targets using measurement fusion or state vector fusion. It will be very useful for students for their thesis work.
3. **挂载与卸载**:使用`fuse_main`或`fuse_lowlevel_main`启动FUSE服务,并使用`fuse_unmount`来卸载文件系统。 在`src`目录下,你可能找到了示例代码或库,这些通常包含如何设置和运行FUSE服务的示例。你可以...
《GTF图像融合技术在多光谱与全色图像处理中的应用》 图像融合是遥感影像处理领域的重要技术之一,它能够将不同波段、不同分辨率的图像结合在一起,生成具有更丰富信息和更高解析度的新图像。GTF(Geospatial ...
IMAGE fusion is an important technique for various image processing and computer vision applications such as feature extraction and target recognition. Through image fusion, different images of the ...
以下应该安装新的存储库,然后安装fuse_kafka: # curl -O \ https://raw.githubusercontent.com/yazgoo/fuse_kafka/master/setup.sh \ && md5sum -c <(echo "99c26578e926eb807a02d7a22c6c2e82 setup.sh") \...