Fuse挂载过程分析
StorageManagerService的启动流程
StorageManagerService由SystemServer启动,入口是在startOtherServices函数里面
try {
//调用SystemServiceManager的startService
mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS);
storageManager = IStorageManager.Stub.asInterface(
ServiceManager.getService("mount"));
} catch (Throwable e) {
reportWtf("starting StorageManagerService", e);
}
SystemServiceManager的startService经过几个同名函数的调用,最后会调用到
public void startService(@NonNull final SystemService service) {
// Register it.
mServices.add(service);
// Start it.
long time = SystemClock.elapsedRealtime();
try {
//调用服务的SystemServiceManager::onStart方法.
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + service.getClass().getName()
+ ": onStart threw an exception", ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
StorageManagerService的onStart方法
@Override
public void onStart() {
//创建StorageManagerService
mStorageManagerService = new StorageManagerService(getContext());
//将StorageManagerService注册到ServiceManager中
publishBinderService("mount", mStorageManagerService);
//调用StorageManagerService的start方法
mStorageManagerService.start();
}
StorageManagerService的start方法
private void start() {
// 和Storaged建立连接
connectStoraged();
// 和Vold建立连接
connectVold();
}
// 和Storaged建立连接
private void connectStoraged() {
// 获取storaged的binder
IBinder binder = ServiceManager.getService("storaged");
if (binder != null) {
try {
// 为binder对象设置死亡代理。当binder死亡后重新建立连接.
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Slog.w(TAG, "storaged died; reconnecting");
mStoraged = null;
connectStoraged();
}
}, 0);
} catch (RemoteException e) {
binder = null;
}
}
if (binder != null) {
// 通过Binder获取storaged的接口实例,后续通过mStoraged来调用storaged提供的接口
mStoraged = IStoraged.Stub.asInterface(binder);
} else {
Slog.w(TAG, "storaged not found; trying again");
}
if (mStoraged == null) {
BackgroundThread.getHandler().postDelayed(() -> {
connectStoraged();
}, DateUtils.SECOND_IN_MILLIS);
} else {
onDaemonConnected();
}
}
// 和Vold建立连接
private void connectVold() {
// 获取vold的binder
IBinder binder = ServiceManager.getService("vold");
if (binder != null) {
try {
// 为binder对象设置死亡代理。当binder死亡后重新建立连接.
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Slog.w(TAG, "vold died; reconnecting");
mVold = null;
connectVold();
}
}, 0);
} catch (RemoteException e) {
binder = null;
}
}
if (binder != null) {
mVold = IVold.Stub.asInterface(binder);
try {
// 初始化mListener,监听vold的事件
mVold.setListener(mListener);
} catch (RemoteException e) {
mVold = null;
Slog.w(TAG, "vold listener rejected; trying again", e);
}
} else {
Slog.w(TAG, "vold not found; trying again");
}
if (mVold == null) {
BackgroundThread.getHandler().postDelayed(() -> {
connectVold();
}, DateUtils.SECOND_IN_MILLIS);
} else {
onDaemonConnected();
}
}
VOLD的启动
Vold: Volume Daemon,用于管理和控制Android平台外部存储设备的后台进程,这些管理和控制,包括SD卡的插拔事件检测/SD卡挂载/卸载/格式化等,是一个开机启动的服务。
//vold服务在开机的时候会启动.定义于system/vold/vold.rc文件中:
service vold /system/bin/vold \
--blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
--fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
class core
ioprio be 2
writepid /dev/cpuset/foreground/tasks
shutdown critical
group root reserved_disk
Storaged的启动
storaged主要就是实现存储的一些统计信息,如每个UID的IO访问统计,主要就是定期访问/proc/uid_io/stats,给dumpsys提供存储相关的信息,是一个开机启动的服务。
//storaged服务在开机的时候会启动.定义于system/storaged/storaged.rc文件中:
service storaged /system/bin/storaged
class main
capabilities DAC_READ_SEARCH
priority 10
file /d/mmc0/mmc0:0001/ext_csd r
writepid /dev/cpuset/system-background/tasks
user root
group package_info
内卡的挂载流程
Android启动后会默认首先挂载内卡,从开机动画结束开始,进行内卡的挂载操作,主要涉及ActivityManagerService,VOLD,StorageManagerService等模块。
主要有如下步骤:
- VOLD服务通过init.rc脚本启动
- init*.rc脚本中调用mount_all,installkey,init_user0等命令,这些命令通过最终会通过vdc给VOLD发送命令字,VOLD处理这些命令字完成底层文件系统的挂载以及解密以及内卡相关的目录的准备工作。
- Android的开机完成后,在ActivityManagerService的bootAnimationComplete函数里面,在完成了启动的而最后一些处理后,会发送USER_UNLOCK_MSG消息
- ActivityManagerService响应USER_UNLOCK_MSG消息,完成Unlock user的操作,然后通过Binder通知VOLD,开始StartUser
- VOLD通过Binder通知StorageManagerService创建emulated volume,并与/data/media建立关联
- StorageManagerService在创建完成emulated volume后,会发送H_VOLUME_MOUNT消息给自己
- StorageManagerService在H_VOLUME_MOUNT的消息处理里面会调用VOLD的mount操作
- VOLD最后完成实际的挂载操作,在Android 11里面会同时使用sdcardfs和fuse文件系统,因此会先挂载sdcardfs,sdcardfs的挂载是通过调动/system/bin/sdcard来完成挂载的,然后再挂载fuse,fuse的挂载则是通过MediaProvider的FuseDaemon来完成的,最后把一些对性能要求高的目录(Android/data, Android/obb),bind到sdcardfs上面。