SDcardFS文件系统浅析(一) - sdcarfs历史
由于安卓O的已经官方支持SDcardFS文件系统,在开发过程中也遇到一些问题,特此浅要分析下SDcardFS
1、Fuse(Filesystem in Userspace)
早期的android系统没有使用fuse文件系统后来android为了控制不同APP对文件访问的权限,使用了fuse文件系统。早期手机内置SD卡使用一个独立vfat文件系统格式的分区。使用fuse之后,将手机内置SD卡与userdata分区合并成为一个分区。userdata分区使用ext4文件系统存储数据,访问userdata分区是直接操作ext4文件系统,而访问内置SD卡,则是先访问fuse文件系统,然后再访问ext4文件系统。
fuse文件系统的基本方法是,创建fuse设备,并将fuse设备挂载到与内置SD卡目录关联的目录。那么,对内置SD卡的访问变成了先访问fuse文件系统,再访问ext4文件系统。fuse的内核部分创建了多个队列,其中包含一个pending队列和一个processing队列。每当有调用者对内置SD卡的系统调用时,fuse把文件访问路径转换为对ext4文件系统的操作路径,设置对应的操作码,并放入一个请求中。fuse在用户态有3个监控线程,循环地读取fuse设备。对fuse设备的读取操作在内核部分转换从pending队列读取请求,如果队列中没有请求,则对应的线程进入睡眠状态。监控线程读取到pending队列中的请求后,把请求转换为对ext4文件系统的系统调用操作。系统调用执行完成后,监控线程把执行结果写入到fuse设备,对fuse设备的写操作在内核部分转换为把结果放入processing队列。processing队列依次取出结果,返回给调用者。
Fuse访问文件流程
维基百科:Fuse文件系统简介
从用户空间到列表文件(ls -l / tmp / fuse)的请求被内核通过VFS重定向到FUSE。FUSE然后执行注册处理程序(./hello)并将请求传递给它(ls -l / tmp / fuse)。处理程序返回一个响应给FUSE,然后它被重定向到最初发出请求的用户空间程序。
由上图可以看出Fuse需要进行多次的用户态与内核态交互,这样就会造成切换开销
实例分析
摘自国外一个博客Why does FUSE on Android suck
cat过程中的strace
root@android: # cd /sdcard root@android:/sdcard # cat test.txt root@android:/sdcard # strace -f -e open,openat,read,close cat test.txt (..) >>stripped output related to loading "cat" by shell<< (..) = 0 openat(AT_FDCWD, "test.txt", O_RDONLY) = 3 read(3, "1234\n", 1024) = 5 read(3, "", 1024) = 0 close(3) = 0
与此同时sdcard daemo 工作流程
root@android: # ps | grep sdcard
media_rw 714 1 23096 1528 ffffffff 81ca6254 S /system/bin/sdcard
root@android: # strace -f -p 714