FUSE 名称含义:用户空间文件系统(Filesystem in Userspace)
功能简述:
对于挂在为fuse文件系统的目录,把本应由内核实现的文件操作,转发给用户层的服务程序去实现。
内核加东西不是那么随便容易的,在用户层,则相对简单容易很多。
添加此中间层后,在用户层想做什么就做什么,功能很强大。
相当于在用户层找了个代理,所有的文件访问都通过上层某个代理程序访问。
Fuse实践了软件工程哲学:在软件工程中,没有一个中间层解决不了的问题!
以及计算机哲学:“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决”
Android R版本 加了这层做了啥?
1. Android把fuse文件系统的文件操作函数全部转发给了用户层的 MediaProvider App;
2. MediaProvider App 里边有个 FuseDaemon.cpp ,此程序是在一个服务内,会一直循环读取 dev/fuse 设备的数据,获取所有对fuse文件系统的访问请求,并作出回应;
3. FuseDaemon.cpp 本身会做一些权限检查,并权限检查文件、访问访问等等相关操作传给 MediaProvider.java;
4. 在 MediaProvider 中做了“文件权限控制”,“分区存储” ,“数据库记录”,“创建文件” 等功能。
5. 其他程序访问 /sdcard/(等同于/storage/emulated/0) 目录除/sdcard/Android/data /sdcard/Android/obb 目录以外的目录,都需要经过fuse文件系统,由 MediaProvider 响应这些文件访问。
原理---图片版
此图摘于网络,我觉得这张图很精简的说明了Fuse文件系统,这里还是用它。图侵删
原理简述---文字版,以open函数为例:
-
应用程序使用“系统调用open”访问挂在为fuse文件系统的目录下的文件,比如 /storage/emulated/0/aaa.txt
c代码示例:int fd = open("/storage/emulated/0/aaa.txt", O_RDWR);
-
进程进入内核虚拟文件系统,调用fuse文件系统的的文件操作open对应的函数
-
即:调用内核代码 source/kernel/msm-5.4/fs/fuse/file.c fuse_open函数
-
fuse_open 最终会调用 request_wait_answer 方法,睡眠等待 用户层fuse服务端程序的响应,即FuseDaemon程序(精灵,守护神)
-
Fuse服务程序,在Android上为 FuseDaemon.cpp ,其在系统启动后,循环读取/dev/fuse 设备。
-
FuseDaemon.cpp读/dev/fuse 设备时,会通过“系统调用”,进入内核 kernel/msm-5.4/fs/fuse/dev.c fuse_dev_do_read 方法
-
fuse_dev_do_read中,会调用 wait_event_interruptible_exclusive 方法,进程进入睡眠,等待fuse文件请求唤醒进程
-
fuse_open 调用 request_wait_answer 睡眠之前,会先调用 queue_request 方法,此方法会调用wake_up方法唤醒 FuseDaemon
-
FuseDaemon 唤醒,再去访问 /storage/emulated/0/aaa.txt 文件。
-
FuseDaemon.cpp 属于 MediaProvider App,MediaProvider 在进程创建时进行bind mount
-
对于 MediaProvider 而言,/storage/emulated 目录并没有挂载为fuse文件系统,直接挂载到了 /data/media/0 目录,即实际的文件系统文件系统
-
FuseDaemon 打开真实文件,获得fd,响应文件访问请求。