写在前面
Android系统中的存储管理是一个复杂而精密的子系统。从SD卡的热插拔检测,到内部存储的分区挂载,再到OBB扩展文件的管理,这一切的核心都离不开一个关键的守护进程------Vold(Volume Daemon)。
作为Android存储架构的"大脑",Vold负责:
- 🔌 设备检测: 实时监听内核Uevent,发现新插入的存储设备
- 📦 Volume管理: 抽象和管理各类存储卷(公共存储、可采用存储、模拟存储)
- 🔐 加密支持: 处理文件级加密(FBE)和磁盘加密
- 🌉 跨进程通信: 通过Binder向Framework层提供存储服务
本文将基于Android 15 (AOSP 15.0) 的源码,深入剖析Vold的架构设计、启动流程、核心组件以及与StorageManagerService的交互机制。
💡 源码路径 : 本文分析的Vold源码位于
system/vold/,StorageManagerService位于frameworks/base/services/core/java/com/android/server/StorageManagerService.java
一、Vold架构总览
1.1 Vold在Android存储架构中的位置
在Android存储架构中,Vold扮演着"承上启下"的关键角色:

如上图所示,Vold的架构可以分为五个层次:
Framework层 (Java)
- StorageManagerService: 系统服务,提供存储管理的Java API
- IStorageManager: AIDL接口,定义Framework层的存储服务接口
Native Binder层 (C++)
- VoldNativeService: 实现IVold接口的Binder服务,是Vold对外提供服务的入口
- IVold: AIDL接口,定义了从Framework到Native的跨进程调用接口
- IVoldListener: AIDL接口,用于Vold向Framework发送事件回调
Vold核心层 (C++)
- VolumeManager: Vold的核心管理器(单例),管理所有Disk和Volume对象
- NetlinkManager: 负责监听内核的Netlink Uevent事件
- NetlinkHandler: 处理Netlink事件,将设备插拔事件转换为Volume操作
存储模型层 (C++)
- Disk: 物理磁盘的抽象(SD卡、USB存储)
- VolumeBase : Volume的基类,提供通用的挂载/卸载接口
- PublicVolume: 公共存储卷(FAT32/exFAT格式)
- PrivateVolume: 可采用存储(Adoptable Storage,ext4加密)
- EmulatedVolume: 模拟存储卷(/storage/emulated)
- ObbVolume: OBB扩展文件卷
底层支持
- Kernel Netlink: 内核Uevent机制,用于设备热插拔事件通知
- /dev/block: 块设备节点
- fstab: 文件系统表配置
1.2 核心设计模式
Vold的设计体现了多个经典的设计模式:
1. 单例模式 (Singleton)
cpp
// system/vold/VolumeManager.h
class VolumeManager {
static VolumeManager* sInstance;
public:
static VolumeManager* Instance();
};
VolumeManager和NetlinkManager都采用单例模式,确保全局只有一个管理器实例。
2. 观察者模式 (Observer)
cpp
// system/vold/VoldNativeService.h
class VoldNativeService : public BinderService<VoldNativeService>, public os::BnVold {
binder::Status setListener(const android::sp<android::os::IVoldListener>& listener);
};
通过IVoldListener接口,StorageManagerService可以订阅Vold的事件通知。
3. 继承多态 (Inheritance)
cpp
// system/vold/model/VolumeBase.h
class VolumeBase {
protected:
virtual status_t doMount() = 0;
virtual status_t doUnmount() = 0;
};
class PublicVolume : public VolumeBase { ... };
class PrivateVolume : public VolumeBase { ... };
各种Volume类型继承自VolumeBase,实现特定的挂载逻辑。
二、Vold启动流程详解
2.1 Init进程启动Vold
Vold作为一个Native守护进程,由init进程根据init.rc配置文件启动:
rc
# system/core/rootdir/init.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
配置解析:
class core: Vold属于核心服务,在early-boot阶段启动--*_context: 指定SELinux上下文,用于blkid和fsck工具的安全隔离ioprio be 2: 设置I/O优先级为Best Effort,优先级2shutdown critical: Vold崩溃会导致系统重启
2.2 main()函数:初始化流程
让我们深入到system/vold/main.cpp的启动代码:
cpp
int main(int argc, char** argv) {
// 1. 初始化日志系统
setenv("ANDROID_LOG_TAGS", "*:d", 1);
android::base::InitLogging(argv, &VoldLogger);
LOG(INFO) << "Vold 3.0 (the awakening) firing up";
// 2. 检测文件系统支持
LOG(DEBUG) << "Detected support for:"
<< (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")
<< (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")
<< (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "");
// 3. 初始化SELinux
sehandle = selinux_android_file_context_handle();
if (!sehandle) {
LOG(ERROR) << "Failed to get SELinux file contexts handle";
exit(1);
}
selinux_android_set_sehandle(sehandle);
// 4. 创建必要的目录
mkdir("/dev/block/vold", 0755);
// 5. 创建核心组件单例
VolumeManager* vm = VolumeManager::Instance();
NetlinkManager* nm = NetlinkManager::Instance();
// 6. 启动VolumeManager
if (vm->start()) {
PLOG(ERROR) << "Unable to start VolumeManager";
exit(1);
}
// 7. 处理fstab配置
VoldConfigs configs = {};
process_config(vm, &configs);
// 8. 启动Binder服务
android::hardware::configureRpcThreadpool(1, false);
if (android::vold::VoldNativeService::start() != android::OK) {
LOG(ERROR) << "Unable to start VoldNativeService";
exit(1);
}
// 9. 启动NetlinkManager
if (nm->start()) {
PLOG(ERROR) << "Unable to start NetlinkManager";
exit(1);
}
// 10. 设置系统属性
android::base::SetProperty("vold.has_adoptable", configs.has_adoptable ? "1" : "0");
android::base::SetProperty("vold.has_quota", configs.has_quota ? "1" : "0");
// 11. Coldboot扫描已连接设备
coldboot("/sys/block");
// 12. 进入主循环
android::IPCThreadState::self()->joinThreadPool();
LOG(INFO) << "vold shutting down";
}

2.3 关键步骤详解
步骤1-2: 日志和文件系统检测
VoldLogger: 自定义日志处理器,early-boot阶段的错误会同时输出到kernel logIsFilesystemSupported(): 检查内核是否支持ext4/f2fs/vfat文件系统
步骤3: SELinux初始化
cpp
sehandle = selinux_android_file_context_handle();
获取SELinux文件上下文句柄,用于后续创建文件时设置正确的安全上下文。
步骤5: 单例创建
cpp
VolumeManager* vm = VolumeManager::Instance();
VolumeManager采用懒加载单例模式:
cpp
VolumeManager* VolumeManager::sInstance = nullptr;
VolumeManager* VolumeManager::Instance() {
if (!sInstance) {
sInstance = new VolumeManager();
}
return sInstance;
}
步骤7: 处理fstab配置
cpp
static int process_config(VolumeManager* vm, VoldConfigs* configs) {
// 读取fstab
if (!ReadDefaultFstab(&fstab_default)) {
PLOG(ERROR) << "Failed to open default fstab";
return -1;
}
// 遍历fstab条目
for (auto& entry : fstab_default) {
// 检查是否支持quota/reserved/compress
if (entry.fs_mgr_flags.quota) configs->has_quota = true;
if (entry.reserved_size > 0) configs->has_reserved = true;
if (entry.fs_mgr_flags.fs_compress) configs->has_compress = true;
// 处理vold_managed标记的分区
if (entry.fs_mgr_flags.vold_managed) {
std::string sysPattern(entry.blk_device);
std::string nickname(entry.label);
int flags = 0;
// 可采用存储标记
if (entry.is_encryptable()) {
flags |= android::vold::Disk::Flags::kAdoptable;
configs->has_adoptable = true;
}
// 添加到VolumeManager
vm->addDiskSource(std::shared_ptr<VolumeManager::DiskSource>(
new VolumeManager::DiskSource(sysPattern, nickname, flags)));
}
}
return 0;
}
fstab示例:
# 可采用的SD卡
/devices/platform/soc/7864900.sdhci/mmc_host/mmc* auto auto defaults vold_managed=sdcard1:auto,encryptable=userdata
步骤11: Coldboot扫描
cpp
static void coldboot(const char* path) {
DIR* d = opendir(path);
if (d) {
do_coldboot(d, 0);
closedir(d);
}
}
static void do_coldboot(DIR* d, int lvl) {
// 遍历/sys/block目录
while ((de = readdir(d))) {
// 向uevent节点写入"add",触发内核发送uevent事件
fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC);
if (fd >= 0) {
write(fd, "add\n", 4);
close(fd);
}
}
}
Coldboot的作用是主动触发内核重新发送已连接设备的uevent事件,确保Vold启动时能发现已插入的存储设备。
三、VolumeManager核心机制
3.1 VolumeManager的数据结构
让我们看看VolumeManager如何组织和管理Disk和Volume:
cpp
// system/vold/VolumeManager.h
class VolumeManager {
private:
std::mutex mLock; // 全局锁
std::mutex mCryptLock; // 加密操作锁
// 核心数据结构
std::list<std::shared_ptr<DiskSource>> mDiskSources; // 磁盘源配置
std::list<std::shared_ptr<android::vold::Disk>> mDisks; // 物理磁盘列表
std::list<std::shared_ptr<android::vold::Disk>> mPendingDisks; // 待处理磁盘
std::list<std::shared_ptr<android::vold::VolumeBase>> mObbVolumes; // OBB卷
std::list<std::shared_ptr<android::vold::VolumeBase>> mInternalEmulatedVolumes; // 模拟卷
// 用户管理
std::unordered_map<userid_t, int> mAddedUsers;
std::set<userid_t> mStartedUsers;
// 事件监听器
android::sp<android::os::IVoldListener> mListener;
};

3.2 Disk和Volume的关系
Disk (物理磁盘抽象):
cpp
// system/vold/model/Disk.h
class Disk {
public:
enum Flags {
kAdoptable = 1 << 0, // 可采用存储
kDefaultPrimary = 1 << 1, // 默认主存储
kSd = 1 << 2, // SD卡
kUsb = 1 << 3, // USB存储
kEmmc = 1 << 4, // eMMC内部存储
};
private:
std::string mId; // 唯一ID,如"disk:179:0"
std::string mSysPath; // sysfs路径,如"/sys/devices/.../mmcblk0"
std::string mDevPath; // 设备路径,如"/dev/block/mmcblk0"
dev_t mDevice; // 设备号(major:minor)
uint64_t mSize; // 磁盘大小
std::string mLabel; // 磁盘标签
int mFlags; // 标志位
std::vector<std::shared_ptr<VolumeBase>> mVolumes; // 包含的Volume列表
};
VolumeBase (Volume基类):
cpp
// system/vold/model/VolumeBase.h
class VolumeBase {
public:
enum class Type {
kPublic = 0, // 公共存储
kPrivate, // 可采用存储
kEmulated, // 模拟存储
kAsec, // 已废弃
kObb, // OBB文件
kStub, // 存根卷
};
enum class State {
kUnmounted = 0, // 未挂载
kChecking, // 检查中
kMounted, // 已挂载
kMountedReadOnly, // 只读挂载
kFormatting, // 格式化中
kEjecting, // 弹出中
kUnmountable, // 无法挂载
kRemoved, // 已移除
kBadRemoval, // 异常移除
};
protected:
virtual status_t doMount() = 0; // 子类实现挂载逻辑
virtual status_t doUnmount() = 0; // 子类实现卸载逻辑
private:
std::string mId; // Volume ID,如"public:179:1"
std::string mDiskId; // 所属Disk ID
Type mType; // Volume类型
State mState; // 当前状态
std::string mPath; // 挂载路径
};

3.3 Volume生命周期管理
创建Volume:
cpp
// system/vold/model/Disk.cpp
void Disk::createPublicVolume(dev_t device) {
auto vol = std::make_shared<PublicVolume>(device);
// 设置Volume属性
vol->setDiskId(getId());
vol->setPartGuid(partGuid);
// 添加到Disk的Volume列表
mVolumes.push_back(vol);
// 创建Volume(通知Framework)
vol->create();
}
挂载Volume:
cpp
// system/vold/model/VolumeBase.cpp
status_t VolumeBase::mount() {
// 1. 状态检查
if (mState != State::kUnmounted) {
LOG(WARNING) << "Already mounted or mounting";
return -EBUSY;
}
// 2. 设置为检查状态
setState(State::kChecking);
// 3. 调用子类实现的挂载逻辑
status_t res = doMount();
// 4. 根据结果更新状态
if (res == OK) {
setState(State::kMounted);
} else {
setState(State::kUnmountable);
}
return res;
}
PublicVolume的挂载实现:
cpp
// system/vold/model/PublicVolume.cpp
status_t PublicVolume::doMount() {
// 1. 读取文件系统类型
std::string fsType;
if (ReadMetadataUntrusted(mDevPath, &fsType, &fsUuid, &fsLabel)) {
LOG(WARNING) << "Failed to read metadata";
fsType = "auto";
}
// 2. 执行fsck检查
if (fsType == "vfat" && vfat::Check(mDevPath)) {
LOG(ERROR) << "FAT filesystem check failed";
return -EIO;
} else if (fsType == "exfat" && exfat::Check(mDevPath)) {
LOG(ERROR) << "exFAT filesystem check failed";
return -EIO;
}
// 3. 创建挂载点
if (PrepareDir(mRawPath, 0700, AID_ROOT, AID_ROOT)) {
PLOG(ERROR) << "Failed to create mount point " << mRawPath;
return -errno;
}
// 4. 执行mount系统调用
if (fsType == "vfat") {
if (vfat::Mount(mDevPath, mRawPath, false, false, false,
AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
PLOG(ERROR) << "Failed to mount vfat";
return -EIO;
}
} else if (fsType == "exfat") {
if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
PLOG(ERROR) << "Failed to mount exfat";
return -EIO;
}
}
// 5. 设置挂载路径
setPath(mRawPath);
return OK;
}
四、Netlink事件处理机制
4.1 Netlink与Uevent
Linux内核通过Netlink Socket向用户空间发送设备事件(Uevent)。Vold通过NetlinkManager监听这些事件,实现设备的热插拔检测。
Uevent事件格式示例:
ACTION=add
DEVPATH=/devices/platform/soc/7864900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0
SUBSYSTEM=block
MAJOR=179
MINOR=0
DEVNAME=mmcblk0
DEVTYPE=disk
4.2 NetlinkManager实现
cpp
// system/vold/NetlinkManager.cpp
int NetlinkManager::start() {
// 1. 创建Netlink socket
mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
if (mSock < 0) {
PLOG(ERROR) << "Unable to create Netlink socket";
return -1;
}
// 2. 绑定到KOBJECT_UEVENT组
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
addr.nl_groups = 0xFFFFFFFF; // 接收所有组的事件
if (bind(mSock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
PLOG(ERROR) << "Unable to bind Netlink socket";
close(mSock);
return -1;
}
// 3. 创建NetlinkHandler并启动监听线程
mHandler = new NetlinkHandler(mSock);
if (mHandler->start()) {
PLOG(ERROR) << "Unable to start NetlinkHandler";
return -1;
}
return 0;
}
4.3 NetlinkHandler处理流程
cpp
// system/vold/NetlinkHandler.cpp
void NetlinkHandler::onEvent(NetlinkEvent* evt) {
VolumeManager* vm = VolumeManager::Instance();
const char* subsys = evt->getSubsystem();
// 只处理block子系统事件
if (!subsys || strcmp(subsys, "block") != 0) {
return;
}
// 根据action类型分发
const char* action = evt->getAction();
if (!strcmp(action, "add")) {
// 设备添加
vm->handleBlockEvent(evt);
} else if (!strcmp(action, "remove")) {
// 设备移除
vm->handleBlockEvent(evt);
} else if (!strcmp(action, "change")) {
// 设备变化(如SD卡写保护开关)
vm->handleBlockEvent(evt);
}
}
4.4 VolumeManager处理块设备事件
cpp
// system/vold/VolumeManager.cpp
void VolumeManager::handleBlockEvent(NetlinkEvent* evt) {
std::lock_guard<std::mutex> lock(mLock);
const char* devpath = evt->findParam("DEVPATH");
const char* action = evt->getAction();
// 解析设备号
int major = std::stoi(evt->findParam("MAJOR"));
int minor = std::stoi(evt->findParam("MINOR"));
dev_t device = makedev(major, minor);
if (!strcmp(action, "add")) {
// 1. 检查是否匹配DiskSource
for (const auto& source : mDiskSources) {
if (source->matches(devpath)) {
// 2. 创建Disk对象
auto disk = std::make_shared<android::vold::Disk>(
eventPath, device, source->getNickname(), source->getFlags());
// 3. 添加到磁盘列表
handleDiskAdded(disk);
break;
}
}
} else if (!strcmp(action, "remove")) {
// 移除对应的Disk
handleDiskRemoved(device);
}
}
void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {
// 1. 添加到mDisks列表
mDisks.push_back(disk);
// 2. 创建Disk(读取分区表,创建Volume)
disk->create();
// 3. 通知Framework
notifyEvent(ResponseCode::DiskCreated,
StringPrintf("%d", disk->getId()));
}
五、Binder通信:Framework与Vold的桥梁
5.1 VoldNativeService架构
VoldNativeService是Vold对外提供服务的Binder接口实现:
cpp
// system/vold/VoldNativeService.h
class VoldNativeService : public BinderService<VoldNativeService>,
public os::BnVold {
public:
static status_t start();
static char const* getServiceName() { return "vold"; }
// Listener管理
binder::Status setListener(const android::sp<android::os::IVoldListener>& listener);
// Volume操作
binder::Status mount(const std::string& volId, int32_t mountFlags, int32_t mountUserId,
const android::sp<android::os::IVoldMountCallback>& callback);
binder::Status unmount(const std::string& volId);
binder::Status format(const std::string& volId, const std::string& fsType);
// Disk操作
binder::Status partition(const std::string& diskId, int32_t partitionType, int32_t ratio);
binder::Status forgetPartition(const std::string& partGuid, const std::string& fsUuid);
// 用户管理
binder::Status onUserAdded(int32_t userId, int32_t userSerial, int32_t sharesStorageWithUserId);
binder::Status onUserRemoved(int32_t userId);
binder::Status onUserStarted(int32_t userId);
binder::Status onUserStopped(int32_t userId);
// FBE加密
binder::Status createUserStorageKeys(int32_t userId, bool ephemeral);
binder::Status destroyUserStorageKeys(int32_t userId);
binder::Status unlockCeStorage(int32_t userId, const std::vector<uint8_t>& secret);
binder::Status lockCeStorage(int32_t userId);
// OBB管理
binder::Status createObb(const std::string& sourcePath, int32_t ownerGid,
std::string* _aidl_return);
binder::Status destroyObb(const std::string& volId);
// 存储维护
binder::Status fstrim(int32_t fstrimFlags,
const android::sp<android::os::IVoldTaskListener>& listener);
};
5.2 StorageManagerService与Vold的交互

完整的SD卡挂载流程:
阶段1: 设备检测(内核→Vold→Framework)
java
// frameworks/base/services/core/java/com/android/server/StorageManagerService.java
private final IVoldListener mListener = new IVoldListener.Stub() {
@Override
public void onDiskCreated(String diskId, int flags) {
// 1. 接收Vold通知:发现新磁盘
synchronized (mLock) {
final DiskInfo disk = new DiskInfo(diskId, flags);
mDisks.put(diskId, disk);
}
// 2. 通知监听器
mHandler.obtainMessage(H_DISK_SCANNED, disk).sendToTarget();
}
@Override
public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
// 3. 接收Vold通知:发现新Volume
synchronized (mLock) {
final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
mVolumes.put(volId, vol);
}
// 4. 发送广播通知应用
mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, vol).sendToTarget();
}
};
阶段2: 挂载请求(Framework→Vold)
java
// StorageManagerService.java
@Override
public void mount(String volId) {
// 1. 权限检查
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
// 2. 查找Volume
final VolumeInfo vol = findVolumeByIdOrThrow(volId);
if (vol.type == VolumeInfo.TYPE_PRIVATE || vol.type == VolumeInfo.TYPE_PUBLIC) {
// 3. 调用Vold挂载
try {
mVold.mount(vol.id, vol.mountFlags, vol.mountUserId,
new IVoldMountCallback.Stub() {
@Override
public void onStatus(int status, PersistableBundle extras) {
// 挂载进度回调
}
});
} catch (Exception e) {
Slog.wtf(TAG, e);
}
}
}
VoldNativeService处理挂载请求:
cpp
// system/vold/VoldNativeService.cpp
binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags,
int32_t mountUserId,
const sp<IVoldMountCallback>& callback) {
ENFORCE_SYSTEM_OR_ROOT;
// 1. 查找Volume
auto vol = VolumeManager::Instance()->findVolume(volId);
if (vol == nullptr) {
return error("Failed to find volume " + volId);
}
// 2. 设置挂载参数
vol->setMountFlags(mountFlags);
vol->setMountUserId(mountUserId);
vol->setMountCallback(callback);
// 3. 执行挂载
int res = vol->mount();
if (res != OK) {
return error("Failed to mount " + volId);
}
return ok();
}
5.3 事件通知机制
Vold通过IVoldListener向Framework发送异步事件:
cpp
// system/vold/VoldNativeService.cpp
void VoldNativeService::notifyDiskScanned(const std::string& diskId, int flags) {
auto listener = VolumeManager::Instance()->getListener();
if (listener) {
listener->onDiskScanned(diskId, flags);
}
}
void VoldNativeService::notifyVolumeStateChanged(const std::string& volId, int state) {
auto listener = VolumeManager::Instance()->getListener();
if (listener) {
listener->onVolumeStateChanged(volId, state);
}
}
六、实战:Vold调试技巧
6.1 查看Vold日志
bash
# 1. 实时查看Vold日志
adb logcat -s vold:*
# 2. 查看Vold错误日志
adb logcat -s vold:E
# 3. 查看特定Volume的日志
adb logcat | grep "public:179:1"
6.2 使用dumpsys分析存储状态
bash
# 1. 查看所有存储信息
adb shell dumpsys mount
# 2. 查看Disk列表
adb shell dumpsys mount | grep "Disk:"
# 3. 查看Volume列表
adb shell dumpsys mount | grep "Volume:"
dumpsys输出示例:
Disks:
disk:179:0 (SD卡):
flags=kSd|kAdoptable
size=31914983424
sysPath=/sys/devices/.../mmcblk0
devPath=/dev/block/mmcblk0
nickname=sdcard1
volumes:
public:179:1
Volumes:
public:179:1 (SD卡):
type=kPublic
diskId=disk:179:0
partGuid=00000000-0000-0000-0000-000000000000
state=kMounted
path=/storage/0000-0000
internalPath=/mnt/media_rw/0000-0000
fsType=vfat
fsUuid=0000-0000
fsLabel=SD Card
6.3 手动触发Vold操作
bash
# 1. 通过vdc(Vold Direct Command)手动挂载Volume
adb shell vdc volume mount public:179:1
# 2. 卸载Volume
adb shell vdc volume unmount public:179:1
# 3. 格式化Volume
adb shell vdc volume format public:179:1 auto
# 4. 分区Disk
adb shell vdc volume partition disk:179:0 public
# 5. 创建OBB Volume
adb shell vdc volume mkobb /data/app/com.example/expansion.obb 1000
6.4 分析Netlink事件
bash
# 1. 监听内核Uevent
adb shell getevent -l /sys/kernel/uevent
# 2. 手动触发coldboot
adb shell "echo add > /sys/block/mmcblk0/uevent"
# 3. 查看设备树
adb shell ls -R /sys/devices/platform/*/mmc_host
6.5 使用Systrace分析存储性能
bash
# 追踪Vold的挂载流程
systrace.py -t 10 -o trace.html sched freq idle am wm gfx view binder_driver \
hal dalvik disk pm ss database package_manager vold
# 在Chrome中打开trace.html,搜索"vold"或"mount"关键字
七、Android 15的Vold新特性
7.1 增强的Adoptable Storage
Android 15对可采用存储进行了优化:
- 更快的格式化速度 : 使用
mkfs.ext4 -E lazy_itable_init,lazy_journal_init - 更好的性能 : 默认启用
discard和noatime挂载选项
7.2 改进的FBE(File-Based Encryption)
cpp
// Android 15新增的FBE API
binder::Status VoldNativeService::setCeStorageProtection(int32_t userId,
const std::vector<uint8_t>& secret) {
// 支持动态修改CE(Credential Encrypted)存储的保护密钥
return translate(fscrypt_set_ce_key_protection(userId, secret));
}
7.3 FUSE Passthrough优化
Android 15引入了FUSE Passthrough机制,减少FUSE带来的性能开销:
cpp
// 启用FUSE Passthrough
if (android::base::GetBoolProperty("persist.sys.fuse.passthrough.enable", false)) {
vol->enablePassthrough();
}
八、常见问题与解决方案
Q1: SD卡插入后无法识别
排查步骤:
-
检查Vold日志是否收到uevent事件:
bashadb logcat -s vold:D | grep "handleBlockEvent" -
检查fstab是否配置了vold_managed:
bashadb shell cat /vendor/etc/fstab* | grep vold_managed -
检查SELinux权限:
bashadb shell getenforce # 应该是Enforcing adb logcat | grep "avc.*denied.*vold"
Q2: Volume挂载失败
常见原因:
- 文件系统损坏:运行
fsck检查 - SELinux上下文错误:检查
/mnt/media_rw的安全上下文 - 权限不足:确保Vold运行在root权限
解决方案:
bash
# 1. 强制fsck检查
adb shell vdc volume fsck public:179:1
# 2. 重新格式化
adb shell vdc volume format public:179:1 vfat
# 3. 重启Vold
adb shell stop vold && adb shell start vold
Q3: Adoptable Storage性能差
优化建议:
-
使用高速SD卡(UHS-I Class 10以上)
-
启用TRIM支持:
bashadb shell sm set-force-adoptable true -
定期运行fstrim:
bashadb shell sm fstrim
总结
本文深入剖析了Android 15的Vold存储管理框架,涵盖了以下核心内容:
- 架构设计: Vold采用分层架构,通过VolumeManager、NetlinkManager等核心组件实现存储管理
- 启动流程: 从init进程启动到Binder服务就绪的完整流程
- Volume管理: Disk和Volume的组织关系,以及Volume的生命周期状态机
- 事件处理: 基于Netlink的设备热插拔检测机制
- Binder通信: VoldNativeService与StorageManagerService的跨进程交互
- 调试技巧: 使用logcat、dumpsys、vdc等工具分析存储问题
Vold作为Android存储架构的核心,其设计体现了单一职责 、分层解耦 、事件驱动等优秀的软件工程思想。理解Vold的工作原理,对于进行存储相关的系统开发和问题排查至关重要。
在下一篇文章中,我们将深入探讨FUSE文件系统与Scoped Storage机制,分析MediaProvider如何通过FUSE实现应用的存储隔离和权限控制。
参考资料
- Android Storage Architecture
- Vold Source Code (AOSP 15.0)
- Android File-Based Encryption
- Android Adoptable Storage
系列文章
欢迎来我中的个人主页找到更多有用的知识和有趣的产品