免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2096 | 回复: 0
打印 上一主题 下一主题

Fuse study [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-31 18:19 |只看该作者 |倒序浏览

                Kernel Version: 2.6.8.1
Fuse Version: fuse-2.5.3
以fuse/example/hello_ll进行分析
重要的数据结构
struct fuse_req: 表示fuse发往fuse上层具体文件系统的的请求.
struct fuse_session: 进行具体文件系统会话管理
struct fuse_chan: 实现具体文件系统与内核(fuse)的交互,主要通过/dev/fuse或者/dev/misc/fuse
工作流程首先编译Fuse,将kernel文件夹下面编译好的Module insmod.
执行命令: $./hello_ll /tmp/ddd/
其作用是利用fuse建立一个文件系统, 并将这个文件系统挂载到/tmp/ddd/下面.
执行过程
执行上述命令后,具体的执行过程如下:
1. fuse_mount(char *mount_point, struct fuse_args *args)
   实现文件系统的挂载,其最终会调用fusermount来执行文件系统的挂载.
   在fuse_mount里面,在执行fusermount前通过socketpair创建全双工通信管道,也就是创建两个进程,并将两个进程的套口文件
   描述符返回,其作用是实现父子进程间全双工通信。fusermount就是在其子进程中完成的。
   在fuse_mount的最后,会执行receive_fd(子进程描述符),从子程接收数据并把接收到数据附属数据缓冲区中所读到的文件描述符
   返回。这个值也是fuse_mount的返回值。
2. fusermount
   fusermount -o fsname=hello_ll -- /tmp/ddd/
   mount parameter: fsname=hello_ll mnt=/tmp/ddd type=fuse flags=6
                    optbuf=fd=4,rootmode=40000,user_id=0,group_id=0
3. 在fuse_mount结束之后,fuse_lowlevel_new会被调用,这个函数是用来建立fuse session的。在这个函数里面,会把
   fuse_ll_process这个函数初始化给新创那的session,所挂载文件系统所有会话都会通过这个函数来完成。
   另外, fuse_lowlevel_new也会把文件系统所定义的操作赋给新创建的session(通过struct fuse_ll->op,最终
   由se->data=fuse_ll完成),这些操作最终决定文件系统的Feature.
4. fuse_kern_chan_new(fd)
   这个部分为创建新的channel,并将channel实例返回。包括初始化channel op, fd, bufsize, and data. 其中op主要是通过
   对channel的读写,实现userspace与Kernel的交互,由fuse_kern_chan_receive和fuse_kern_chan_send两个函数完成读
   写功能。fd正是上面fuse_mount所返回的fd的值。也是channel进行交互所使用的文件描述符。
5. fuse_session_add_chan(se, ch), 把channel实例赋给session。
6. fuse_session_loop(se), 这个函数主要实现文件系统挂载后的Daemon。
   fuse_chan_receive(ch, buf, bufsize),调用fuse_kern_chan_receive从Kernel里面读数据。
   fuse_session_process(se, buf, res, ch), 对于上面读出的数据,在这里最终交给fuse_ll_process函数进行处理。
use_ll_process
从上面我们看到,程序最终通过fuse_ll_process这个函数完成了文件系统的大部分功能,下面我们看看它具体做了什么:
首先,它从上面receive函数中读到的数据里面读出in->opcode,也就是所执行的命令具体执行的动作,然后,跟据相应的
opcode, 执行们们在创建session时所注册的文件系统的相关函数。下面以ls命令为例对其进行简单说明:
1. $cd /tmp/ddd
2. $ls
那么相应的它会执行:OPENDIR, GETATTR, READDIR, LOOKUP, READDIR, RELEASEDIR几个动作,详细的执行过
程请参考busybox中coreutils/ls.c源码。
FUSE Kernel Module
在上面的fuse_session_loop中我们提到两个函数:
(1)fuse_chan_receive(ch, buf, bufsize), 在这个函数里,会调用read(ch->fd, buf, size),从channel内读取信息,
也就是从Kernel中把对文件系统相应的请求信息读出来。
在Kernel里面,fuse module的fuse_dev_read(struct file *file, char __user *buf,size_t nbytes, loff_t *off)被
调用。
struct iovec iov. iov->iov_len = nbytes; iov->iov_base = buf;
最终通过使用fuse_dev_readv函数,这个函数作用是读取一个请求到文件系统的用户空间。这里也使用到我们上面提的
到的重要数据结构struct fuse_req req在这里也被使用,主要用来读出request in信息。接下来通过fuse_copy_one
把in->h的信息存放到iov->buf里面。在此之前,已经通过fuse_copy_init将iov初始化为iov->write=1,iov->req = req,
iov->iov=iov,cs->nr_segs = nr_segs;
read的最后,会执行fuse_copy_args(cp request argument to userspace buffer)-->fuse_copy_pages(cp pages in
the request to userspace buffer)
(2) int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],size_t count),这个函数是在对上
面的请求之后被调用的,它主要是调用writev来回应上面的request。在Kernel里面,writev所对应的函数为
fuse_dev_writev(struct file *file, const struct iovec *iov,unsigned long nr_segs, loff_t *off),它用来实现
写回一个前面request的应答,
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/97267/showart_1950627.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP