赞
踩
FUSE(用户态文件系统)是一个实现在用户空间的文件系统框架,通过FUSE内核模块的支持,使用者只需要根据fuse提供的接口实现具体的文件操作就可以实现一个文件系统。
在fuse出现以前,Linux中的文件系统都是完全实现在内核态,编写一个特定功能的文件系统,不管是代码编写还是调试都不太方便,就算是仅仅在现有传统文件系统上添加一个小小的功能,因为是在内核中实现仍需要做很大的工作量。在用户态文件系统FUSE出现后(2.6内核以后都支持fuse),就会大大的减少工作量,也会很方便的进行调试。编写FUSE文件系统时,只需要内核加载了fuse内核模块即可,不需要重新编译内核。
fuse主要由三部分组成:FUSE内核模块、用户空间库libfuse以及挂载工具fusermount。
#define fuse_main(argc, argv, op, user_data) \
fuse_main_real(argc, argv, op, sizeof(*(op)), user_data)
内核模块由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()函数),
1.一个用户进程发出read文件请求;
2.该请求被转换为一个内核系统调用,内核VFS层调用fuse文件系统内核模块;
3.fuse 内核模块通过/dev/fuse,将read请求传递到fuse 用户态进程;
4.fuse daemon根据用户实现的read接口,产生新的系统调用,最终调用ext4文件系统的read操作函数,从存储介质中提取读操作要求的数据(page cache中有,直接从其中获取,否则读磁盘);
5.内核将数据返回给fuse文件系统;
6.用户级文件系统再次调用内核操作,把数据返回给用户进程;
7.内核将数据传给用户进程完成操作。
1.先打开设备文件/dev/fuse;
2.然后挂载FUSE文件系统;
3.产生FUSE文件系统指针;
4.初始化FUSE文件系统的操作函数集:
5.初始化信号处理函数集;
6.进入等待循环:
从设备文件/dev/fuse中读取来自内核模块的请求;
运行相应的操作函数,并获取返回结果;
将返回给内核的应答结果写入设备文件/dev/fuse中;
fuse本质上(数据处理时)是处于现有文件系统之上的(具体实现是和现有文件系统处于同一个层次的),fuse不参与底层磁盘数据的存取,只负责处理对读取和写入的数据在逻辑上的操作而已。
软件包下载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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。