- 浏览: 203826 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
Prepared:
Hadoop的几个明显缺点 -
CSunDNan:
...
openjdk jvm 方法字节码执行过程 -
幻影之蚀:
...
mysql 源码分析2 源码调试环境建立 -
shukongchengje:
紧急呼唤楼主,mysql代码从哪里弄?官网wiki上看的一头雾 ...
mysql源码分析 整体架构 -
yeshaoting:
好文章.不介意的话转载了.
jvm 字节码中文含义
fuse处理请求的整个流程如下图所示,以unlink操作为例进行说明。其中“>”表示调用,”<”表示返回,[]表示调用中所做的工作。本人结合fuse的源代码,对整个流程进行了分析。
fuse通过fuse_session_loop(或对应多线程的方法)来启动fuse守护程序,守护程序不断的从/dev/fuse上读取请求,并处理。
代码片段1
int fuse_session_loop(struct fuse_session *se) //在fuse_main中会被调用,或其多线程版本
{
int res = 0;
struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
size_t bufsize = fuse_chan_bufsize(ch);
char *buf = (char *) malloc(bufsize); //为channel分配好缓冲区
if (!buf) {
fprintf(stderr, "fuse: failed to allocate read buffer\n");
return -1;
}
//fuse daemon, loops
while (!fuse_session_exited(se)) {
struct fuse_chan *tmpch = ch;
//分析见代码片段2,从/dev/fuse读请求,会等待一直到有请求为止
res = fuse_chan_recv(&tmpch, buf, bufsize);
if (res == -EINTR)
continue;
if (res <= 0)
break;
fuse_session_process(se, buf, res, tmpch); //处理读到的请求
}
free(buf);
fuse_session_reset(se);
return res < 0 ? -1 : 0;
}
//代码片段2
int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
{
struct fuse_chan *ch = *chp;
if (ch->compat)
return ((struct fuse_chan_ops_compat24 *) &ch->op)
->receive(ch, buf, size);
else
return ch->op.receive(chp, buf, size);
//由下面的一段代码可以发现,receive最终是通过fuse_kern_chan_receive实现的,代码片段3分析该请求
}
#define MIN_BUFSIZE 0x21000
struct fuse_chan *fuse_kern_chan_new(int fd)
{
//channel的读写方法
struct fuse_chan_ops op = {
.receive = fuse_kern_chan_receive,
.send = fuse_kern_chan_send,
.destroy = fuse_kern_chan_destroy,
};
//设置bufsize大小
size_t bufsize = getpagesize() + 0x1000;
bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;
return fuse_chan_new(&op, fd, bufsize, NULL);
}
代码片段3
static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
size_t size)
{
struct fuse_chan *ch = *chp;
int err;
ssize_t res;
struct fuse_session *se = fuse_chan_session(ch);
assert(se != NULL);
// 一直轮询,直到读到请求为止
restart:
//fuse_chan_fs获取到/dev/fuse的文件描述符,调用read系统调用从设备读取请求
res = read(fuse_chan_fd(ch), buf, size);
//根据fuse设备驱动程序file结构的实现(dev.c),read将调用fuse_dev_read,该方法最终通过fuse_dev_readv实现,根据代码中的注释,fuse_dev_read做了如下工作:
Read a single request into the userspace filesystem's buffer. This
function waits until a request is available, then removes it from
the pending list and copies request data to userspace buffer.
if no data: goto restart
………
}
以上的分析对应了fuse filesystem daemon做的第一部分工作。当用户从控制台输入"rm /mnt/fuse/file"时,通过VFS(sys_unlink),再到fuse(dir.c中实现的inode_operations,file.c中实现的file_operations中的方法都会最终调用request_send,后面会介绍),这个请求最终被发到了/dev/fuse中,该请求的到达会唤醒正在等待的fuse守护程序,fuse守护程序读取该请求并进行处理,接下来介绍处理请求所作的工作。
代码片段4
struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
const struct fuse_lowlevel_ops *op,
size_t op_size, void *userdata)
{
//fuse_lowlevel_ops在之前的文章http://blog.chinaunix.net/u2/87570/showart_2166461.html中已经介绍过了,开发者实现了fuse_lowlevel_ops并传递给fuse_lowlevel_common
struct fuse_ll *f;
struct fuse_session *se;
struct fuse_session_ops sop = {
//最终调用的处理方法
.process = fuse_ll_process, //分析见代码片段5
.destroy = fuse_ll_destroy,
};
…….
}
代码片段5
static void fuse_ll_process(void *data, const char *buf, size_t len,
struct fuse_chan *ch)
{
struct fuse_ll *f = (struct fuse_ll *) data;
struct fuse_in_header *in = (struct fuse_in_header *) buf;
const void *inarg = buf + sizeof(struct fuse_in_header);
struct fuse_req *req;
//创建并初始化一个请求
req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
if (req == NULL) {
fprintf(stderr, "fuse: failed to allocate request\n");
return;
}
req->f = f;
req->unique = in->unique;
……
//根据opcode调用fuse_ll_ops中相应的方法,fuse_ll_ops的介绍http://blog.chinaunix.net/u2/87570/showart_2166461.html
fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
}
}
以上代码对应中流程中perform unlink的工作,实际上就是执行开发者实现的一组方法来完成相关的工作,接下来就是把执行完请求后需要的数据返回,最终是通过send_reply实现的,
代码片段6
static int send_reply(fuse_req_t req, int error, const void *arg,
size_t argsize)
{
struct iovec iov[2];
int count = 1;
if (argsize) {
iov[1].iov_base = (void *) arg;
iov[1].iov_len = argsize;
count++;
}
return send_reply_iov(req, error, iov, count);
}
static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
int count)
{
……
res = fuse_chan_send(req->ch, iov, count);
free_req(req);
return res;
}
static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
size_t count)
{
if (iov) {
//将数据写到/dev/fuse上,最终会调用fuse_dev_write
ssize_t res = writev(fuse_chan_fd(ch), iov, count);
……
return 0;
}
另外fuse接收到VFS的请求时,通过request_send将请求发送到/fuse/dev,并调用request_wait_answer等待返回结果。至于fuse使用的队列的管理,在流程图中也做了简单的说明,下一篇文章将详细分析队列的管理。
代码片段7
void request_send(struct fuse_conn *fc, struct fuse_req *req)
{
req->isreply = 1;
spin_lock(&fc->lock);
if (!fc->connected)
req->out.h.error = -ENOTCONN;
else if (fc->conn_error)
req->out.h.error = -ECONNREFUSED;
else {
//将请求加入请求队列
queue_request(fc, req);
/* acquire extra reference, since request is still needed
after request_end() */
__fuse_get_request(req);
//等待结果
request_wait_answer(fc, req);
}
spin_unlock(&fc->lock);
}
fuse通过fuse_session_loop(或对应多线程的方法)来启动fuse守护程序,守护程序不断的从/dev/fuse上读取请求,并处理。
代码片段1
int fuse_session_loop(struct fuse_session *se) //在fuse_main中会被调用,或其多线程版本
{
int res = 0;
struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
size_t bufsize = fuse_chan_bufsize(ch);
char *buf = (char *) malloc(bufsize); //为channel分配好缓冲区
if (!buf) {
fprintf(stderr, "fuse: failed to allocate read buffer\n");
return -1;
}
//fuse daemon, loops
while (!fuse_session_exited(se)) {
struct fuse_chan *tmpch = ch;
//分析见代码片段2,从/dev/fuse读请求,会等待一直到有请求为止
res = fuse_chan_recv(&tmpch, buf, bufsize);
if (res == -EINTR)
continue;
if (res <= 0)
break;
fuse_session_process(se, buf, res, tmpch); //处理读到的请求
}
free(buf);
fuse_session_reset(se);
return res < 0 ? -1 : 0;
}
//代码片段2
int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
{
struct fuse_chan *ch = *chp;
if (ch->compat)
return ((struct fuse_chan_ops_compat24 *) &ch->op)
->receive(ch, buf, size);
else
return ch->op.receive(chp, buf, size);
//由下面的一段代码可以发现,receive最终是通过fuse_kern_chan_receive实现的,代码片段3分析该请求
}
#define MIN_BUFSIZE 0x21000
struct fuse_chan *fuse_kern_chan_new(int fd)
{
//channel的读写方法
struct fuse_chan_ops op = {
.receive = fuse_kern_chan_receive,
.send = fuse_kern_chan_send,
.destroy = fuse_kern_chan_destroy,
};
//设置bufsize大小
size_t bufsize = getpagesize() + 0x1000;
bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;
return fuse_chan_new(&op, fd, bufsize, NULL);
}
代码片段3
static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
size_t size)
{
struct fuse_chan *ch = *chp;
int err;
ssize_t res;
struct fuse_session *se = fuse_chan_session(ch);
assert(se != NULL);
// 一直轮询,直到读到请求为止
restart:
//fuse_chan_fs获取到/dev/fuse的文件描述符,调用read系统调用从设备读取请求
res = read(fuse_chan_fd(ch), buf, size);
//根据fuse设备驱动程序file结构的实现(dev.c),read将调用fuse_dev_read,该方法最终通过fuse_dev_readv实现,根据代码中的注释,fuse_dev_read做了如下工作:
Read a single request into the userspace filesystem's buffer. This
function waits until a request is available, then removes it from
the pending list and copies request data to userspace buffer.
if no data: goto restart
………
}
以上的分析对应了fuse filesystem daemon做的第一部分工作。当用户从控制台输入"rm /mnt/fuse/file"时,通过VFS(sys_unlink),再到fuse(dir.c中实现的inode_operations,file.c中实现的file_operations中的方法都会最终调用request_send,后面会介绍),这个请求最终被发到了/dev/fuse中,该请求的到达会唤醒正在等待的fuse守护程序,fuse守护程序读取该请求并进行处理,接下来介绍处理请求所作的工作。
代码片段4
struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
const struct fuse_lowlevel_ops *op,
size_t op_size, void *userdata)
{
//fuse_lowlevel_ops在之前的文章http://blog.chinaunix.net/u2/87570/showart_2166461.html中已经介绍过了,开发者实现了fuse_lowlevel_ops并传递给fuse_lowlevel_common
struct fuse_ll *f;
struct fuse_session *se;
struct fuse_session_ops sop = {
//最终调用的处理方法
.process = fuse_ll_process, //分析见代码片段5
.destroy = fuse_ll_destroy,
};
…….
}
代码片段5
static void fuse_ll_process(void *data, const char *buf, size_t len,
struct fuse_chan *ch)
{
struct fuse_ll *f = (struct fuse_ll *) data;
struct fuse_in_header *in = (struct fuse_in_header *) buf;
const void *inarg = buf + sizeof(struct fuse_in_header);
struct fuse_req *req;
//创建并初始化一个请求
req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
if (req == NULL) {
fprintf(stderr, "fuse: failed to allocate request\n");
return;
}
req->f = f;
req->unique = in->unique;
……
//根据opcode调用fuse_ll_ops中相应的方法,fuse_ll_ops的介绍http://blog.chinaunix.net/u2/87570/showart_2166461.html
fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
}
}
以上代码对应中流程中perform unlink的工作,实际上就是执行开发者实现的一组方法来完成相关的工作,接下来就是把执行完请求后需要的数据返回,最终是通过send_reply实现的,
代码片段6
static int send_reply(fuse_req_t req, int error, const void *arg,
size_t argsize)
{
struct iovec iov[2];
int count = 1;
if (argsize) {
iov[1].iov_base = (void *) arg;
iov[1].iov_len = argsize;
count++;
}
return send_reply_iov(req, error, iov, count);
}
static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
int count)
{
……
res = fuse_chan_send(req->ch, iov, count);
free_req(req);
return res;
}
static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
size_t count)
{
if (iov) {
//将数据写到/dev/fuse上,最终会调用fuse_dev_write
ssize_t res = writev(fuse_chan_fd(ch), iov, count);
……
return 0;
}
另外fuse接收到VFS的请求时,通过request_send将请求发送到/fuse/dev,并调用request_wait_answer等待返回结果。至于fuse使用的队列的管理,在流程图中也做了简单的说明,下一篇文章将详细分析队列的管理。
代码片段7
void request_send(struct fuse_conn *fc, struct fuse_req *req)
{
req->isreply = 1;
spin_lock(&fc->lock);
if (!fc->connected)
req->out.h.error = -ENOTCONN;
else if (fc->conn_error)
req->out.h.error = -ECONNREFUSED;
else {
//将请求加入请求队列
queue_request(fc, req);
/* acquire extra reference, since request is still needed
after request_end() */
__fuse_get_request(req);
//等待结果
request_wait_answer(fc, req);
}
spin_unlock(&fc->lock);
}
发表评论
-
fuse-2.7.3.tar.gz开源代码学习心得
2010-03-30 14:06 2537fuse-2.7.3.tar.gz开源代码 ... -
Linux网络文件系统
2010-03-30 13:25 1945Linux网络文件系统 (NFS) ... -
基于MySQL的数据库集群系统的实现
2010-03-29 15:27 828您的WebApp系统是否正在 ... -
gearman 源码分析
2010-03-29 15:23 1950gearman 源码分析 -
lustre 基于对象存储的分布式实现
2010-03-29 15:20 1124lustre 基于对象存储的分布式实现 -
揭开j2ee集群面纱
2010-03-29 15:09 682揭开j2ee集群面纱 -
gearman 分布式图片转化处理框架
2010-03-29 15:07 867gearman 分布式图片转化处理框架 -
lustre文件架构 dht
2010-03-29 15:03 909lustre文件架构 dht ib总线 -
Quartz源码分析
2010-03-29 14:10 2379Quartz是运用最广的任务调度框架,它最核心的组成部分是Sc ... -
Terracotta/Quartz集成带来了基于内存集群的分布式任务调度功能
2010-03-18 13:21 1247Terracotta/Quartz集成带来了基于内存集群的分布 ... -
Lustre File System (转)
2010-03-16 17:03 1652Lustre File System 历史 Lustr ... -
Hadoop的几个明显缺点
2010-03-16 16:56 15017Hadoop的几个明显缺点如下: 1. 采用Java实现。Ja ... -
HDFS是一个不错的分布式文件系统
2010-03-16 16:55 1230HDFS是一个不错的分布式文件系统,它有很多的优点,但也存在有 ... -
Lustre系统的体系结构
2010-03-16 16:51 1081Lustre的主要组件有三个:先进的集群文件系统,基于对象的存 ... -
分布式文件系统 linux lustre
2010-03-16 16:48 2186Lustre名字是由Linux和Clusters演化而来,是为 ... -
gluster分析(转)
2010-03-16 16:45 4023引言 GlusterFS 是一个高层次的分布式文件系统解决方案 ... -
分布式文件系统 gluster
2010-03-16 16:44 1120分布式文件系统 gluster -
分布式锁资料
2010-03-16 16:44 841分布式锁服务 -
分布式调度框架 quartz
2010-03-16 16:39 1460分布式调度框架 quartz -
分布式调度 gearman(转)
2010-03-16 16:38 1399学学Gearman2009年07月11日 ...
相关推荐
描述了fuse的框架,组成部分,包括(用户态和内核态),以write为例分析了整个用户态和内核态的流程
本文仅针对Fuse(熔断器)选型,PPTC&CPTC及其他过流保护装置或电路不在其列。针对Fuse设计选型相关基础知识介绍及选型参考标准、选型方法介绍等内容。
Fuse React是用React钩子编写的(React的新特性允许您在不编写类的情况下使用状态和其他React特性)。 Fuse React是一个完整的React管理模板,遵循谷歌的材料设计指南。 Fuse React管理模板使用Material UI V5作为...
FUSE文件系统参考
fuse-2.8.4
fuse的最新版本,fuse是用户自己空间上的文件系统,
Fuse ESB 4.3.1 个人使用 笔记
fuse-2.9.3.tar.gz
这个是fuse文件系统的源码,网上找起来麻烦!所以从内核中打包然后提供下载
to repair fuse bit in avr
FUSE(用户空间文件系统)作为类UNIX系统平台上可加载的内核模块,允许非特权用户创建功能完备的文件系统,而不需要重新编译内核。FUSE模块仅仅提供kernel模块的接入口,而本身的主要实现代码位于用户空间中。对于...
针对Fuse选型相关的参数特性,讲解参数选型的计算过程,选型注意事项。定义Fuse选型的规范方法。定义Fuse选型的规范方法。
fuse-2.8.6.tar.gz
fuse source code. version is 2.9.2
Fuse Angular 11/React双版本后台模版,具有开箱即用的AoT编译器支持以及完整的NgRx示例应用程序。 内置应用 日历应用 电子商务应用 邮件应用 邮件(NgRx)应用 聊天应用 文件管理器应用 联系人应用 待办事项 Scrum...
安装脚本:./configure;make; make install 挂载:modprobe fuse 验证:lsmod|grep fuse
详细介绍了关于fuse的参数规格及使用,希望对大家家有用......
linux 下挂载硬盘 fuse 自己找的
fuse, 用于实现FUSE文件系统的goto包 这个包允许用户从Go写入和安装用户空间文件系统。 按如下方式安装:go get -u github.com/jacobsa/fuse之后,请参阅以下三个软件包的文档:包 fuse插件提供了对挂载新文件系统
fuse-2.7.4.tar版本,解压缩,即可编译安装。