赞
踩
fuse主要由三部分组成:FUSE内核模块、用户空间库libfuse以及挂载工具fusermount。
1.在用户态程序调用fuse_main() (lib/helper.c)时,先调用fuse_setup_common()该函数先解析用户态程序传递过来的参数,然后调用fuse_mount_common()(该函数是fuse_kern_mount()函数的封装,lib/mount.c)。
fuse_main()是一个宏定义(include/fuse.h),如下:
- #define fuse_main(argc, argv, op, user_data) \
- fuse_main_real(argc, argv, op, sizeof(*(op)), user_data)
2.fuse_kern_mount()函数中调用fuse_mount_fusermount()使用socketpair()创建一个UNIX域套接字,然后使用创建子进程执行fusermount程序,将FUSE_COMMFD_ENV环境变量中套接字的一端传递给它。
3.fusermount(util/fusermount.c)确保fuse 模块已经被加载,然后打开/dev/fuse并通过一个UNIX套接字发送文件处理句柄。父进程等待子进程执行完毕回收,然后返回fuse_mount_fusermount()函数。
4.fuse_kern_mount()通过/dev/fuse返回文件句柄给fuse_kern_chan_new()负责处理内核数据,然后返回到fuse_mount_common()函数。
5.fuse_setup_common()函数调用fuse_new_common(lib/fuse.c),fuse_new_common()函数分配fuse数据结构,存储并维护一个文件系统数据镜像缓存cached,返回到fuse_main()。
6.最后,fuse_main()调用fuse_loop(lib/fuse.c)或者fuse_loop_mt()(lib/fuse_mt.c),这两个函数都可以从设备/dev/fuse读取文件系统调用,调用fuse_main()之前调用存储在fuse_operations结构体中的用户态函数。这些调用的结果回写到/dev/fuse设备(这个设备可以转发给系统调用)。
内核模块由2个部分组成:
第一个是proc文件系统组件(在kernel/dev.c中);
第二个是文件系统调用(kernel/file.c、kernel/inode.c、kernel/dir.c)。
kernel/file.c、kernel/inode.c、kernel/dir.c中的所有系统调用要么调用request_send(),要么调用request_send_noreply()或者request_send_nonblock()。大部分都是调用request_send()函数,它添加请求到“list of request”结构体(fc->pending),然后等待一个响应。request_send_noreply()和request_send_nonblock()与request_send()函数相似,除了是非阻塞的和不响应一个回复。
kernel/dev.c中的proc文件系统组件响应文件IO请求,fuse_dev_read()处理文件读,并从请求列表结构体(list of requests)返回命令到调用程序。fuse_dev_write()处理文件写, 完成数据写并放入req->out结构体(它能返回系统调用通过请求列表结构体和request_send()函数),
该fuse文件系统挂载在现有ext4文件系统之上.
1.一个用户进程发出read文件请求;
2.该请求被转换为一个内核系统调用,内核VFS层调用fuse文件系统内核模块;
3.fuse 内核模块通过/dev/fuse,将read请求传递到fuse 用户态进程;
4.fuse daemon根据用户实现的read接口,产生新的系统调用,最终调用ext4文件系统的read操作函数,从存储介质中提取读操作要求的数据(page cache中有,直接从其中获取,否则读磁盘);
5.内核将数据返回给fuse文件系统;
6.用户级文件系统再次调用内核操作,把数据返回给用户进程;
7.内核将数据传给用户进程完成操作。
库函数fuse_main()具体处理流程:
软件包下载https://github.com/libfuse/libfuse/releases:
下载软件包,解压后,编译安装。
- ./configure
- make
- make install
解压后的目录中有名为example的目录,其中有fuse自带的几种fuse用户态实现例子,可以运行其进行测试。
fuse安装完后,该目录中的文件也已经编译成功,只需运行即可(目录dir为挂载点,挂载成功后,在该目录中对文件的操作就会调用fuse自己实现的操作函数):
//example/hello.c 部分代码,主要实现文件系统的取文件属性、打开目录、读文件、打开文件
- static struct fuse_operations hello_oper = { //文件操作函数,为回调函数
-
- .getattr = hello_getattr,
- .readdir = hello_readdir,
- .open = hello_open,
- .read = hello_read,
- };
- int main(int argc, char *argv[])
- {
- return fuse_main(argc, argv, &hello_oper, NULL); //主函数,会调用文件操作结构体
-
- }
-
-
- ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ mkdir dir //创建挂载点
- ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ ./hello dir //将hello fuse文件系统挂载在dir目录上

根据目前实现的四个功能进行测试如下:
- ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ ls
- hello
- ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ cat hello
- Hello World!
- ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ ls -l hello
- -r--r--r-- 1 root root 13 12月 31 1969 hello
- ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ rm -fr hello
- rm: cannot remove ‘hello’: Function not implemented
-
- ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ touch test
- touch: cannot touch ‘test’: Function not implemented
- ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ mkdir test
- mkdir: cannot create directory ‘test’: Function not implemented
由测试可以发现在dir目录中只能对文件进行实现的四个功能的操作,其他的操作都无法完成,会提示用户函数没有实现。
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/$ dirfusermount -u dir //卸载fuse文件系统dir
原文链接:https://blog.csdn.net/ty_laurel/article/details/51685193
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。